【问题标题】:Why heap memory still accessible after HeapFree为什么堆内存在 HeapFree 之后仍然可以访问
【发布时间】:2019-11-04 14:29:22
【问题描述】:

我写了一个简单的 C 程序来创建一个单链表。有用;例如,我将一些数字推送到一个列表中,print_list(...) 函数将这些数字打印到控制台。

但是,我随后添加了一个clear_list(...) 函数并在print_list(...) 之前调用它,看看会发生什么。调用clear_list 后,print_list 仍然像以前一样打印数字。

print_list 如何从释放的内存中打印数字?我使用HeapAlloc 分配列表结构,使用HeapFree 解除分配。

代码如下:

static BOOL push_list(DWORD a)
{
    LIST *ptr = NULL;

    ptr = (PLIST)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,     sizeof(LIST));
    if (ptr == NULL)
    {
        printf("Error push list\n");
        return FALSE;
    }

    ptr->i = a;

    ptr->next = LIST_HEAD;
    LIST_HEAD  = ptr;


    return TRUE;
}



void free_dir_list(void)
{
    PLIST pTemp = NULL;
    P_LIST PTR = LIST_HEAD;


    while (PTR != NULL)
    {
        pTemp = PTR;
        PTR = PTR->next;
        HeapFree(GetProcessHeap(), 0, pTemp);
    }
}

【问题讨论】:

  • 为什么在 HeapFree 之后内存不能访问?这不是 VirtualFree。释放后使用内存的任何方式都是UB。这里可以是任何结果
  • 阅读:stackoverflow.com/a/6445794/584518。这是关于局部变量超出范围但同样的推理可以应用于 free() 之后的堆变量。
  • 当你释放内存时,它并没有物理消失。并且释放功能不会修改它释放的内存的数据。访问不属于你的内存(比如释放后)会导致未定义的行为
  • 我说过这些不正确的内存访问是“未定义的行为”,而 C 中的未定义行为是一个有趣的概念。这意味着任何事情都可能发生。您可能会收到一条错误消息,也可能不会。它可能会如你所愿,也可能不会。它可能今天做一件事,明天做另一件事。
  • 如果当您调用例如:char *buf = malloc(15000000); 时,您没有收到NULL 响应,那么是的,您可以使用内存。如果在您致电free(buf); 之后,您不应该 尝试使用它。 (注意,您尝试分配的内存块越大,NULL 响应发生的机会就越高。)另外,请阅读 undefined behavior 上的此链接。

标签: c windows winapi heapalloc


【解决方案1】:

在 C 中使用释放的内存是未定义的行为。

它在这里工作是因为在内存被释放后没有任何改变。这通常是在内存被释放后立即出现的情况。 HeapFree(...) 或标准 C free(...) 之类的函数 通常会将内存归零;它们只是改变运行时管理的内部状态,这样内存就被认为是空闲的。

【讨论】:

    猜你喜欢
    • 2010-10-08
    • 2013-10-11
    • 2015-09-30
    • 1970-01-01
    • 2013-04-12
    • 2021-06-09
    • 2012-07-01
    • 2020-12-28
    • 1970-01-01
    相关资源
    最近更新 更多