在free()之后使用指针

在我的testing中,我发现在free()之后可以使用指针。 我有以下代码:

typedef struct{ int module_id; int adc_id; struct config_line * pnext; } config_line; config_line * create_list() { config_line * phead = (config_line *) malloc(sizeof(config_line)); phead->pnext=NULL; phead->module_id = 1; phead->adc_id = 2; printf("module_id=%d adc_id=%d\n",phead->module_id, phead->adc_id); free(phead); printf("module_id=%d adc_id=%d\n",phead->module_id, phead->adc_id); phead->module_id = 2; phead->adc_id = 5; printf("module_id=%d adc_id=%d\n",phead->module_id, phead->adc_id); } 

这个代码的输出是:

 module_id=1 adc_id=2 module_id=0 adc_id=2 module_id=2 adc_id=5 

为什么免费(后)我可以访问(读写)指针? 为什么没有分段错误?

Solutions Collecting From Web of "在free()之后使用指针"

因为使用无效指针会调用未定义的行为。 这意味着行为是…好的… 未定义的。 它没有被迫崩溃。

当你调用free(phead) ,内存phead指向正在释放,但是phead的值不变,使phead成为悬挂指针 。 访问已被释放的内存会导致未定义的行为

一旦释放它指向的内存空间,并不是指向NULL指针的好习惯:

 free(phead); phead = NULL; 

因为内存仍然映射到你的进程中,但是没有被分配。 在C程序中有两个级别的内存管理:首先,内核给你你可以写入的页面。 如果进程需要更多内存,它必须从内核(sbrk)请求更多内存。 尽管如此,malloc还是会把它分成几块,根据需要请求更多的页面,但是使用已经分配给程序的可能内存。 自由不能返回一个页面,直到所有使用它的分配已被释放。

所以,内核给你的内存访问冲突(SIGSEGV)是相当粗糙的,不能捡到大多数的内存错误,只能从内核的角度来看是致命的。 您可以自由地清理您的malloc的跟踪数据,读取大部分分配的结尾以及多次释放之后,依此类推。

不要提交内存错误。 使用非常严格的虚拟机valgrind运行你的应用程序来检查所有的错误,并立即压扁它们。

因为释放内存(一个指针)只是将内存放回空闲内存池。 内存不会消失,内存不会被清除,直到内存被重新分配并写入。

所以,在释放内存之后,访问内存是非常有可能的。 就像你想象的那样,不是一个好主意,因为它可以随时分配和修改。

为什么一只鸡不管头被砍掉,还是会继续跑来跑去? 请注意,这并不总是发生; 一些鸡可能立即停止移动,而另一些鸡可能会继续运行数月 。 当它发生时,就会发生,因为它发生了。 这是否意味着我们应该把我们的宠物关掉?

就像把我们的宠物砍掉一样,使用已经释放的记忆是一个坏主意。 这并不意味着会产生负面的结果; 你的程序可能会继续在你的机器上按预期运行,而if (fubar) (其中fubar是你的无效指针)可能足以导致你的程序在其他实现中出现故障。

这种实现自由的定义(或不​​)行为在形式上被称为未定义的行为 ; 行为是未定义的,因为C标准(一组规定C实现应该如何行为的文档) 没有定义行为 。 因此,就像切断我们的宠物,我们应该避免所有未定义的行为。