【问题标题】:C - Storing pointers with malloc() in an array, can't free() them afterwardsC - 将带有 malloc() 的指针存储在数组中,之后不能 free() 它们
【发布时间】:2017-12-09 16:19:56
【问题描述】:

我想将使用malloc() 分配的pointers 存储在array 中,然后将它们全部存储在free 中。然而,即使程序没有抱怨它也不起作用。在cleanMemManager() 下面实际上不会是free 内存,因为在main() 内部测试时,char* 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;
}

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

【问题讨论】:

  • 关于:void* ptr = malloc(size); 1) 始终检查 (!=NULL) 返回值以确保操作成功。 2) 函数malloc() 需要一个类型为size_t 而不是int 的参数。 (此隐式转换可能会失败,因为 size_t 未签名而 int 已签名。)

标签: c arrays pointers memory-management malloc


【解决方案1】:

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 语言不是很好的语言。

【讨论】:

  • 是的 sizeof(void*) 事情是我的坏事,我在搞乱三指针并忘记将其恢复。感谢您提供其他信息。
【解决方案2】:

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

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

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

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

另外free() 不会清理/清零分配的空间,该块被简单地标记为“空闲”。数据很可能会在内存中保留片刻,直到空闲块被另一个 malloc 请求覆盖。

【讨论】:

    猜你喜欢
    • 2021-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    • 2018-02-26
    • 2016-07-30
    • 1970-01-01
    相关资源
    最近更新 更多