释放 void 指针数组的元素

Freeing elements of a void pointer array

我正在调试其他人编写的一些代码,Valgrind 检测到有多个内存泄漏。我认为导致问题的部分代码涉及 void 指针:

int noElements = 100;
void** ptr = malloc( noElements * sizeof(void*));
for(int i = 0; i < noElements; i++)
{
    ptr[i] = malloc(sizeof(void*));
}

//Operation filling the array and doing calculation

free(ptr); //This will not clear the underlying array causing the memory leak?

我创建了一个小测试程序来检查错误是否在我认为的位置(在调用 free(ptr); 之前没有释放每个 ptr[i]),但是我在尝试释放元素时遇到错误。我的测试程序如下所示:

int main()
{
    int num = 10000000; //Large array so I can clearly see memory usage
    void** ptr = (void**) malloc(sizeof(void*) * num);

    for (int i = 0; i < num; i++)
    {
        ptr[i] = malloc(sizeof(void*));
        ptr[i] = &i;    //If I never point elements at anything, this code works
    }

    for (int i = 0; i < num; i++)
    {       
        free(ptr[i]);       //Crashes here if the elements have been pointed at a variable
    }
    free(ptr);  

    return 0;
}

如果实际上已经分配了指针,为什么在每个数组元素上调用 free 会导致程序崩溃?

在你的代码中

  ptr[i] = &i;

产生三个问题。

  1. 它使 malloc() 实际返回的指针丢失(你正在覆盖它),所以你没有机会在 free()-稍后编辑它,导致 memory leak.
  2. i 是局部作用域变量(for 循环体的作用域),并且您正在存储要在作用域外使用的变量的地址(即,在生命周期结束后)。在范围之外尝试访问它的地址将调用 undefined behavior.
  3. (Ignoring point 2) Attempt to free() the ptr[i] will cause undefined behavior again, as the pointer is not returned by memory分配器函数。

你的指针被分配了一个不是你想要的值。

for (int i = 0; i < num; i++)
{
    ptr[i] = malloc(sizeof(void*));
    ptr[i] = &i;    //If I never point elements at anything, this code works
}

首先,您分配一个由 malloc() 返回的有效内存地址。 使用 free() 可以免费使用此地址。 但是随后您分配了另一个地址。您的局部变量的地址 i。此内存位置未使用 malloc() 分配,因此无法释放。通过分配此地址,您丢失了导致内存泄漏的动态分配地址。

您的评论有误。您已经分配了一个 ptr[i] 指向某个有效地址的值。您无需再次分配。而你不应该。