尝试使用free()来理解它是如何工作的

use*_*983 24 c debugging malloc free pointers

为了理解C编程语言中free的用法,我尝试在Ubuntu上运行此代码,但是在运行EXE文件时,我收到了SIGABRT错误.为什么程序没有正常退出?

#include<stdio.h>
#include<stdlib.h>

int main()
{
   int ret;
   int *ptr;
   ptr = (int *)malloc(sizeof(int)*10);
   free(ptr);
   ptr = &ret;
   free(ptr);
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

Car*_*rum 38

试图释放你没有得到的指针malloc(或其中一个朋友)会导致未定义的行为.你的第二次free(ptr)电话尝试就是这样.

从C规范,§7.22.3.3 free函数,第2段:

free函数使得指向的空间ptr被释放,即可用于进一步分配.如果ptr是空指针,则不执行任何操作.否则,如果参数与先前由内存管理函数返回的指针不匹配,或者如果通过调用freeor 释放了空间realloc,则行为未定义.


Mah*_*mer 11

   ptr = &ret;
   free(ptr);
Run Code Online (Sandbox Code Playgroud)

是相同的:

    free(&ret);
Run Code Online (Sandbox Code Playgroud)

ret驻留在堆栈上,而不是堆上.尝试在堆上free()未分配(使用malloc()等)的内存将导致未定义的行为.


Ale*_*lex 11

虽然所有未定义的行为答案都是正确的,但查看实现可能会更有帮助.

我认为非常好的参考是K&R C malloc.关于它是如何工作的解释在"The C Programming Langugage",第8.7章中.

请记住,在C语言中查看来自标准库函数的代码时,它们具有实现和规范,其中实现可能具有其规范不需要的可重现行为.

基本上几乎所有malloc实现都有一个空闲列表,用于管理列表(或多个列表)中的空闲内存区域.自由列表通常以某种方式处理,free多次调用内存区域会使此列表处于不正确的状态.

当有目的地制作数据结构时,也可以调用恶意行为.Phrack有一篇关于如何free在破坏freelist 时传递无效内存时调用代码执行的文章.

其他malloc实现也可能值得关注(这是一个不完整的分配库列表).


Ash*_*que 9

该功能free()仅适用于已分配的内存heap通过malloc().不适用于静态分配,因为静态分配是自动处理的.这是错误:

 int ret; 

 ptr = &ret;

 free(ptr);
Run Code Online (Sandbox Code Playgroud)

您无法执行此操作,因为ret未在堆上分配内存.它位于堆栈中,只应释放堆的内存.


Rah*_*thi 8

free(ptr)当您尝试释放未分配的指针时,您的第二个导致未定义的行为.另请注意,静态分配会自动回收,因此您不需要它们来释放它.


Jee*_*tel 5

  ptr = &ret;
   free(ptr);
Run Code Online (Sandbox Code Playgroud)

在这里,您尝试释放本地存储堆栈变量的内存.根据规则,你不应该释放它.当main()退出堆栈上的所有本地存储内存时,总是获得空闲.

免费仅适用于堆分配内存.