我正在调试其他人编写的一些代码,这些代码被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;
产生三个问题。
- 它使实际返回的指针
malloc()
丢失(您正在覆盖它(,因此您以后无法free()
-ing 它,从而导致内存泄漏。 -
i
是一个局部作用域变量(循环体的作用域for
(,并且您正在存储要在作用域之外使用的变量的地址(即,在生存期结束后(。在作用域之外尝试访问其地址将调用未定义的行为。 - (忽略第 2 点(尝试
free()
ptr[i]
将再次导致未定义的行为,因为内存分配器函数不会返回指针。
你的指针被分配了一个不是你想要的值。
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]
指向某个有效地址的值。您无需再次分配。你不应该。