指针算术运算后释放指针

5

我的问题非常简单。假设我们有:

char* ptr = (char*) malloc(sizeof(char)*SIZE);
ptr+= SIZE/2;
free(ptr);

当我们释放指针时会发生什么?这是一种未定义的操作吗?它是否会释放所有的SIZE缓冲区还是只释放剩余的SIZE/2? 提前感谢您为我澄清这个问题。


谢谢大家,非常具体的答案,现在我知道如何在我的引擎中处理它了。我以为会出现崩溃,直到我实际尝试了它,使用gcc和c++并没有得到任何错误或崩溃。我认为它混乱了我的内存,如果不处理,迟早会变成相当恶劣的东西。 - Lefteris
1
请注意,在C语言中,从malloc返回的结果不需要进行强制类型转换。 - Lundin
5个回答

11

你的程序可能会崩溃:在C语言中,free()操作其实非常简单,但它只能用于原始分配的地址。

典型的内存分配器的工作方式如下伪代码:

  • 申请64字节
  • 分配器分配了70字节(多6个字节)
  • 前2个字节设置为“签名”,一个被分配器识别的模式,用于标识由它分配的内存
  • 接下来的4个字节表示已分配的大小
  • 返回一个指针,指向第7个字节的开始位置

因此,当你调用 free(ptr) 时,分配器会在指针之前的6个字节处检查签名。如果找不到签名,它就会崩溃 :)


非常好的解释,谢谢。我知道有签名但不确定具体细节。 - Lefteris

8
如果传递给free()的参数不匹配之前使用malloc()等函数分配的指针,则行为是未定义的。您很可能会在libc版本中遇到分段错误或失败的断言。
离题提示:在C中最好不要转换malloc()的结果。

谢谢你的回答,迈克尔。我主要使用C++进行编码,在那里我认为这是标准做法。我不知道关于C和malloc的事情。我会记住的,谢谢。 - Lefteris

2

这种行为是未定义的,很可能会导致分段错误 - 这还是“好”的情况。在最糟糕的情况下,它将损坏程序的内存并引起各种奇怪的错误和错误输出。


2

在大多数实现中,这应该会导致某种致命错误。您只能释放已分配缓冲区的开头。

在Windows上(使用Visual Studio编译器),您通常会遇到“非有效堆指针”的错误。在Linux上,如phihag所述,通常会导致分段错误。在两种情况下,这是一个运行时错误,通常会终止程序的执行。


2

行为是未定义的。我猜你会得到一个段错误...这就是当我在我的系统中尝试时得到的结果。

free()需要调用者传递一个由内存分配器函数(如malloc())返回的地址。其他任何东西都会导致未定义的行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接