free()后使用指针

Yur*_*uri 4 c linux

在我的测试中,我发现在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);
}
Run Code Online (Sandbox Code Playgroud)

此代码的输出是:

module_id=1 adc_id=2
module_id=0 adc_id=2
module_id=2 adc_id=5
Run Code Online (Sandbox Code Playgroud)

为什么在free(phead)之后我可以访问(读写)指针?为什么没有分段错误?

小智 20

因为使用无效指针会调用未定义的行为.这意味着行为......好吧...... 未定义.它没有义务崩溃.


Lih*_*ihO 12

当你调用时free(phead),内存phead指向被释放,但是phead不变的值保持不变,成为phead一个悬空指针.访问已释放的内存会产生未定义的行为.

NULL一旦释放它指向的内存,分配给指针是一个好习惯:

free(phead);
phead = NULL;
Run Code Online (Sandbox Code Playgroud)

  • @PeterMiehle:我不是说给指针分配"NULL"将解决世界上所有的问题,所有程序员都会过得很开心.我只是说如何避免创建额外的悬空指针是一个很好的做法. (3认同)
  • 分配NULL ...总是没有帮助,所以它更隐蔽,可能会影响另一个bug.(head = malloc(); list = head; free(head); head = NULL; => list仍然指向freeeded memory) (2认同)

aut*_*tic 6

鸡的头被砍掉了,为什么还能继续跑跳?请注意,这并不总是发生;有些鸡可能会立即停止活动,而另一些鸡可能会继续奔跑数月。当它确实发生时,它会发生,因为它发生了。这是否意味着我们应该砍掉宠物的头?

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

这种实现定义(或不​​定义)行为的自由思想正式称为未定义行为;该行为是未定义的,因为 C 标准(一组规定 C 实现应如何行为的文档)没有定义该行为。因此,就像砍掉宠物的头一样,我们应该避免所有不确定的行为。


Nic*_*son 5

因为内存仍映射到您的进程中,但未分配。C程序中有两个级别的内存管理:首先,内核为您提供了可以写入的页面。如果该进程需要更多已映射的内存,则它必须向内核(sbrk)请求更多。但是,这需要很大的块,因此malloc为您将其切成块,根据需要请求更多的页面,但要使用已分配给程序的可能内存。在释放使用该页面的所有分配之前,free无法返回该页面。

因此,内核给您的内存访问冲突(SIGSEGV)相当粗略,并且无法处理大多数内存错误,只有从内核角度来看这是致命的事情。您可以随意破坏malloc的跟踪数据,可以在大多数分配结束之后读取数据,也可以在许多释放之后读取数据,等等。

但是永远不要提交内存错误。使用使用非常严格的VM的valgrind运行您的应用程序,以检查所有错误并立即消除它们。


Zif*_*ion 5

因为释放内存(指针)只是将该内存放回到空闲内存池中。内存不会消失,并且直到再次分配并写入该内存时,它的内容才会被清除。

因此,在内存被释放后,很可能对其进行访问。只是不像你想象的那样是一个好主意,因为它可以随时分配和修改。