free()后使用指针

时间:2013-03-15 12:10:48

标签: 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);
}

此代码的输出为:

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

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

5 个答案:

答案 0 :(得分:18)

因为使用无效指针会调用未定义的行为。这意味着行为......好...... 未定义。 强制崩溃。

答案 1 :(得分:9)

当您致电free(phead)时,指向的内存phead正在被释放,但phead的值保持不变,使phead成为悬空指针。访问已释放的内存会产生未定义的行为

一旦释放指向的内存,将NULL指定给指针是一个好习惯:

free(phead);
phead = NULL;

答案 2 :(得分:4)

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

因此,内核为您提供的内存访问违规(SIGSEGV)相当粗糙,并且无法从内核的角度来看大多数内存错误。您可以随意删除malloc的跟踪数据,读取大多数分配结束后以及许多自由之后,等等。

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

答案 3 :(得分:4)

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

因此,在释放内存后,很有可能访问内存。你可以想象的不是一个好主意,因为它可以随时分配并修改。

答案 4 :(得分:2)

为什么一只鸡会继续奔跑跳跃,尽管它被砍掉了?请注意,这不会始终发生;有些鸡可能会立即停止移动,others might continue to run around for months。当它确实发生时,它会发生,因为它发生了。这是否意味着我们应该切断我们的宠物头?

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

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