1

I am creating a function to split a char * into an array of other char * based on a target (which can be " ", "a", etc). In this example, I am using a white space (" ") to split my char * into an array of char *.

However, I am having some difficulties dealing with the dynamically allocated memory. I allocated memory for both the array of char * that I will be returning as the split function return value, and another one to copy each separated const * that I am reading from the main char * parameter.

#define MAX_SIZE 65535
#define MAX_SPLIT_SIZE 1023

char** a_split(char * x, const char * target, int sn){

    char ** sa = nullptr;

    size_t t_len = strnlen(target, MAX_SIZE);
    if(t_len < 1 || t_len > MAX_SIZE){ return sa; }

    int split_num = 0;

    if(sn > 1 && sn < MAX_SPLIT_SIZE){

        sa = new char * [sn + 1]();
        split_num = sn;


    }else if(sn == -1){

        sa = new char * [MAX_SPLIT_SIZE + 1];
        split_num = MAX_SPLIT_SIZE;
    }else {
        return sa;
    }

    char * ptr = x;
    char * mi;                                              // Match index.

    int i = 0;                                              // Index of 'sa' array.

    while((mi = std::strstr(ptr, target)) && split_num--){

        size_t dif = mi - ptr;

        char * n_cstring = new char[dif + 1]();

        memcpy(n_cstring, ptr, dif);                        // Copying content to new string.

        sa[i++] = n_cstring;                                // Append new string to 'sa' array of split strings.

        ptr += dif;

        ptr += t_len;

        delete [] n_cstring; // <------- This is causing some weird errors.
    }

    if(mi == nullptr){

        sa[i] = ptr;
    }

    return sa;
}

int main(int argc, char * argv[]){

    char  c[] = "I love Thanos";

    char ** x = a_split(c, " ", -1);

    for(int i = 0; x[i]; i++){
        puts(x[i]);
    }

    return 0;
}

I found out that when using 'delete [] n_cstring', instead of outputting the char *'s separately (like in "I" "love" "Thanos"), it is outputting "love" "love" "Thanos". It is making this kind of repetition for every example. Why is 'delete' doing this?

Also, as I am returning a dynamically allocated array ('sa'), where would you recommend me to delete it? - the main function does not recognize 'sa'.

4
  • 1
    How about using std::vector<std::string> ? Commented Mar 8, 2018 at 14:31
  • "a const *" is not a thing. Please clarify what you're talking about. const is an adjective. Commented Mar 8, 2018 at 14:31
  • When you say char* x = new ... I read that as std::string x; without the need for delete or the need to worry about its size Commented Mar 8, 2018 at 14:32
  • "the main function does not recognize 'sa'" - If you don't understand function calls and return values yet, I recommend staying away from dynamic memory allocation for now. Commented Mar 8, 2018 at 14:33

1 Answer 1

1

One problem is that you are deleting n_cstring too soon: since you are storing it in sa[] array, i.e.

sa[i++] = n_cstring;

deleting it right after that in the loop leaves sa[i] hanging. The end result is that your main would have undefined behavior, in addition to having memory leaks due to never deleting sa.

I am returning a dynamically allocated array (sa), where would you recommend me to delete it?

There is only one place where this could be done - it's main. You put sa into x, so you need to invoke delete[] x once you are done printing.

Note that since delete[] n_cstring must be removed from a_split function, main must also delete the individual elements of x before deleting x itself.

The best approach by far is to change your code to use std::vector<std::string>. This would free you from allocating and deleting character arrays, fixing potential crashes automatically.

Sign up to request clarification or add additional context in comments.

7 Comments

@MauriceFigueiredo That's because you didn't set sa elements to nullptr after the allocation inside a_split. The parts that you did allocate will be deleted normally, but once you hit the first uninitialized "junk" element you'll see "deleting memory that has not been allocated" error.
@MauriceFigueiredo Yes, main must delete what has been allocated, and that is what your for loop does. The problem is that your for loop does not stop after deleting what's been allocated, because extra cells inside sa (aka x) contain uninitialized junk.
@MauriceFigueiredo Your approach is right. Make sure you set all sa to nullptr right after the allocation. If the error remains, run your code with valgrind to see what else is going on.
@MauriceFigueiredo If you delete only x, you have a memory leak. Did you try running valgrind? You can download it here. This tool is essential for memory profiling.
@MauriceFigueiredo Put your for loop back into main and try valgrind again. This time you will see the problem.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.