我希望在[{1}}中使用pointers
存储malloc()
,然后在array
之后存储free
。然而,即使该计划没有抱怨它也不起作用。 cleanMemManager()
以下free
实际上main()
内存与在pointer
内测试时的内容* NULL
不是???
并且会打印{{1} }}
码
#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;
}
我不理解用于此的语法,指针实际上根本没有触及吗?什么是释放,因为它不会抛出任何错误?
答案 0 :(得分:5)
在main
中,char *ptr = (char*)talloc(3);
声明ptr
为本地变量。它包含talloc
返回的值的副本,并且您的子例程都不知道ptr
或它在哪里。所以他们都没有改变ptr
的价值。因此,当您到达if (ptr != NULL)
时,ptr
的值未发生变化。
此外:
在initMemManager
中,您应该在sizeof(void *)
的两个地方使用sizeof(void**)
。在这些地方,您要分配和复制void *
个对象,而不是void **
个对象。
看起来你正在尝试实现一种智能内存管理器,当它们被释放时自动设置指向NULL
的指针。要在C中执行此操作,您必须放弃使用指针的副本。例如,ptr
是ptrList[0]
的副本,但tfree
仅设置传递给NULL
的副本。我们可以提供构建这样一个系统的建议,但它会很快变得很麻烦 - 你的内存管理器需要保存一个指针及其副本的数据库(以及从它们派生的指针,如通过数组算法)。或者你必须通过ptrList
数组间接引用所有内容,这会给你的源代码增加一些混乱。不幸的是,C不是一个好的语言。
答案 1 :(得分:3)
Freeing不保证指向已分配块的指针将设置为NULL。如果你真的尝试做
if (ptrList[0] != NULL)
printf("ptrList[0] != NULL");
您将看到程序不会输出,如果您删除cleanMemManager()
函数调用,它将输出。这意味着tfree
函数正在按预期工作,它释放了已分配的内存。
现在为什么ptr
变量未设置为NULL,这只是因为ptr
仍然存储旧地址。 cleanMemManager()
无法改变变量ptr
。这通常称为悬空指针或在空闲后使用。
同样free()
不会清除/清零分配的空间,该块只是标记为“空闲”。数据很可能会暂时保留在内存中,直到空闲块被另一个malloc
请求覆盖。