C - 在数组中使用malloc()存储指针,之后不能释放()它们

时间:2017-12-09 16:19:56

标签: c arrays pointers memory-management malloc

我希望在[{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;
}

我不理解用于此的语法,指针实际上根本没有触及吗?什么是释放,因为它不会抛出任何错误?

2 个答案:

答案 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中执行此操作,您必须放弃使用指针的副本。例如,ptrptrList[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请求覆盖。