C语言 对指向动态声明的数组元素的指针调用free



当我运行以下代码时:

int main(int* argc, char** argv) {
int* array = malloc(5 * sizeof(int));
free(array + 3);
}

我得到错误pointer being freed was not allocated。我的直觉是,free不是试图释放array的第四个元素,而是试图释放在其最后一个元素之后的3*sizeof(int)字节。这是正确的吗?如果是这样,为什么会发生这种情况?执行该程序所产生的行为是否总是可预测的,还是未定义的或特定于实现的?

free希望您使用从malloc返回的相同地址,否则可能会发生任何事情。malloc调用每次调用分配一个完整的段,在本例中为5int大。释放这个段的一部分是没有意义的,这不是堆的工作方式。

堆首先分配一个段头,这是一个内部信息,包含大小等。标头之后是所有的数据。这个头部分对程序员来说是不可见的,它是如何实现的是特定于操作系统和/或C库的。

实际上,在你的情况下,你传递了一个位于3*sizeof(int)字节的地址到段的数据部分,这不是一个有效的地址,因为free需要malloc使用的初始地址,以便知道该段的内部头从哪里开始。当您传递错误的地址给它时,它可能会抓取随机数据的其他部分并将其视为标头。行为未定义。

(然而,你可以传递一个空指针给free(),这保证是一个无操作。)

From specifications offree():

简介

#include <stdlib.h>
void free(void*ptr);

free函数导致ptr所指向的空间被释放,也就是说,可供进一步分配。如果ptr是空指针,则不进行任何操作。否则,如果参数与之前由内存管理函数返回的指针不匹配,或者如果空间已经被调用freerealloc释放,则行为未定义。

因此,你要做的是未定义行为

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf

malloc分配内存块。

您只能取消分配(free)此块。不能释放单个元素或块的一部分。

你可以重新分配(realloc)这个块,使它更大或更小。

最新更新