【发布时间】: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