将字符串连接到数组时发生内存泄漏

时间:2019-01-29 04:44:29

标签: c

我有一个函数alloc_str,它使用一个字符串指针和一个指针数组。它动态地将数组的大小增加一,并将字符串追加到数组中。我已经运行了GDB调试器,并在下面突出显示了我的内存泄漏和const错误。

我期望的输入/输出:

array = alloc_str(array, "test_1");
array = alloc_str(array, "test_2");
array = alloc_str(array, "test_3");
--> ["test_1", "test_2", "test_3"]

我的alloc_str函数:

char **alloc_str(char **existing, const char *add)
{
    int length = 0; //find the length of the array
    for (; existing[length]; length++)
    {
    }
    //allocate memory to copy array array
    char **existing_c = (char **)calloc(length + 2, sizeof(char *));

    for (int i = 0; i < length; i++) //copy original array into new array
    {
        existing_c[i] = existing[i];
    }

    //possible memory leak error
    strncat(existing_c, add, sizeof(existing_c) - strlen(existing_c) - 1);
    existing_c[sizeof(existing_c)-1] = '\0';
    //possible memory leak error
    strncpy(existing, existing_c, sizeof(existing - 1));
    s_copy[sizeof(destsize)-1] = '\0'; //error here

    free(existing);
    return existing_c;
}

void free_array(char **strings) //free's data in array, should be fine
{
    int length = 0;
    for (; strings[length]; length++)
    {
    }
    strings = (char **)calloc(length + 2, sizeof(char *));
}

我的主要功能:

#include<string.h>
#include<stdio.h>
#include<stdlib.h>

int main(){ //should be fine
    char **array = NULL;
    char **test;

    array = (char **)calloc(1, sizeof(char *)); //array has no strings yet

    array = alloc_str(array, "test_1");
    array = alloc_str(array, "test_2");
    array = alloc_str(array, "test_3");


    for (test = array; *test; test++)
    {
        printf("%s\n", *test);
    }

    free_array(array);
}

我的错误:

Subscript of pointer to function type 'void (const void *, void *, size_t)' (aka 'void (const void *, void *, unsigned long)')

2 个答案:

答案 0 :(得分:2)

存在多个问题:

char **alloc_str(char **existing, const char *add)
{
    int length = 0; //find the length of the array
    for (; existing[length]; length++)
    {
    }
    //allocate memory to copy array array
    char **existing_c = (char **)calloc(length + 2, sizeof(char *));

    for (int i = 0; i < length; i++) //copy original array into new array
    {
        existing_c[i] = existing[i];
    }

    ////////////////////////////////////
    //possible memory leak error
    strncat(existing_c, add, sizeof(existing_c) - strlen(existing_c) - 1);
    existing_c[sizeof(existing_c)-1] = '\0';
    //possible memory leak error
    strncpy(existing, existing_c, sizeof(existing - 1));
    s_copy[sizeof(destsize)-1] = '\0'; //error here
    ////////////////////////////////////

    free(existing);
    return existing_c;
}

标有////////////////////////////////////的部分没有多大意义。

您分配了一个指针数组。不要像对待字符串一样对待它。它不是字符串。 相反,只需将新指针分配给数组的末尾并再次添加终止符即可。

    existing_c[length] = add;
    existing_c[length+1] = NULL;

有了该终结器,您可以使用普通的malloc而不是calloc,因为您仍然可以分配数组的所有元素。

除了分配问题之外,还有另一个内存泄漏:

void free_array(char **strings) //free's data in array, should be fine
{
    int length = 0;
    for (; strings[length]; length++)
    {
    }
    strings = (char **)calloc(length + 2, sizeof(char *));
}

将指针传递给指针数组。该数组占用一些您之前用calloc分配的内存。 然后,您分配更多的内存,并将地址分配给局部变量string

这有两个问题:

  1. 先前分配的内存不会释放。
  2. 您无法在该函数之外访问在此函数中分配的内存。

最后,您的free_array函数不会释放任何东西,但会占用更多内存。

存储在该数组中的字符串可能会出现另一个问题。 在您的示例中,您使用字符串文字。这些是静态对象,无需释放它们。

如果您还将使用函数存储指向动态分配的字符串的指针,则还需要注意分配和释放字符串。

答案 1 :(得分:1)

strncat()在包含NUL终止(也称为“ C”)字符串的内存缓冲区上工作:

char buf[10] = {'a', 'b', 'c', '\0'};
strncat(buf, "def", sizeof(buf) - strlen(buf) - 1);
assert(strcmp(buf, "abcdef") == 0);  // buf now equals to "abcdef"

(好吧,strlen()的使用有点抵消了strncat()优于好的strcat()的好处,但这是另一个故事……)

因此,它与您在运动中想要做的非常不同。您实际上不需要strncat()strncpy()中的任何一个。