复制到新阵列时出现动态内存分配问题

时间:2018-03-08 14:30:10

标签: c++ arrays heap-memory

我正在创建一个函数,根据目标(可以是“”,“a”等)将char *拆分为其他char *的数组。在这个例子中,我使用一个空格(“”)将我的char *拆分成一个char *数组。

但是,我在处理动态分配的内存时遇到了一些困难。我为char *数组分配了内存,我将作为split函数返回值返回,另一个用于复制我从主char *参数中读取的每个分离的const *。

#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;
}

我发现当使用'delete [] n_cstring'时,不是单独输出char *(比如“I”“love”“Thanos”),而是输出“love”“love”“Thanos” ”。每个例子都在做这种重复。为什么'删除'这样做?

另外,当我返回一个动态分配的数组('sa')时,你会建议我删除它吗? - 主要功能无法识别'sa'。

1 个答案:

答案 0 :(得分:1)

一个问题是您要过早删除n_cstring:因为您将其存储在sa[]数组中,即

sa[i++] = n_cstring;

在循环之后立即删除它会使sa[i]挂起。最终结果是,main除了因永不删除sa而导致内存泄漏外,还会有未定义的行为。

  

我正在返回一个动态分配的数组(sa),你建议我在哪里删除它?

只有一个地方可以做到这一点 - 它是main。您将sa放入x,因此您需要在完成打印后调用delete[] x

请注意,由于必须从delete[] n_cstring函数中删除a_split,因此main必须删除x的各个元素,然后再删除x

到目前为止,最好的方法是将代码更改为使用std::vector<std::string>。这将使您免于分配和删除字符数组,自动修复潜在的崩溃。