C - 将带有 malloc() 的指针存储在数组中,之后无法释放它们



我想将使用malloc()分配的pointers存储在array中,然后在之后free所有这些。但是,即使该程序不抱怨,它也不起作用。下面的cleanMemManager()实际上不会free内存,因为当在内部测试时main()字符*pointer没有NULL,它会打印???

法典:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void **ptrList = NULL;
void tfree(void** ptr)
{
free(*ptr);
*ptr = NULL;
}
void* talloc(int size)
{
void* ptr = malloc(size);
ptrList[0] = ptr;   ///No clue if this actually does what I think it does
return ptrList[0];
}
void initMemManager()
{
ptrList = (void**)malloc(sizeof(void**) * 3);
memset(ptrList, 0, sizeof(void**) * 3);
}
void cleanMemManager()
{
tfree(&ptrList[0]); //Doesn't free the right pointer it seems
}
int main()
{
initMemManager();
char* ptr = (char*)talloc(3);
cleanMemManager();
if (ptr != NULL) //This will trigger and I'm not expecting it to
printf("???");
getchar();
return 0;
}

我不明白用于此目的的语法,指针实际上根本没有被触摸吗?既然它不会抛出任何错误,那么它释放了什么呢?

main中,char *ptr = (char*)talloc(3);声明ptr是一个局部变量。它包含talloc返回的值的副本,并且您的子例程都不知道ptr或它在哪里。所以它们都不会改变ptr的值。因此,当你达到if (ptr != NULL)时,ptr的值没有改变。

此外:

  • initMemManager中,您应该在两个有sizeof(void**)的地方使用sizeof(void *)。在这些位置,您分配和复制的是对象void *而不是void **对象。

  • 看起来您正在尝试实现一种智能内存管理器,该管理器可以在释放指针时自动设置指向NULL的指针。要在 C 中做到这一点,你必须放弃拥有指针的副本。例如,ptrptrList[0]的副本,但tfree只设置它传递给NULL的任何副本。我们可以为构建这样一个系统提供建议,但它很快就会变得很麻烦 - 您的内存管理器需要保留一个指针及其副本的数据库(以及从它们派生的指针,如通过数组算术)。或者你必须通过该ptrList数组间接引用所有内容,这会给你的源代码增加一些混乱。不幸的是,C 不是一种好的语言。

释放不保证指向已分配块的指针将设置为 NULL。如果你真的尝试做

if (ptrList[0] != NULL)
printf("ptrList[0] != NULL");

您将看到程序不会输出,如果删除cleanMemManager()函数调用,它将输出。这意味着tfree函数按预期工作,它正在释放分配的内存。

现在至于为什么ptr变量没有设置为 NULL,这仅仅是因为ptr仍在存储旧地址。cleanMemManager()无法改变变量ptr。这通常称为悬空指针或释放后使用。

此外,free()没有清理/清零分配的空间,该块只是标记为"空闲"。数据很可能会在内存中保留片刻,直到空闲块被另一个malloc请求覆盖。

相关内容

  • 没有找到相关文章

最新更新