C语言中的C, free()和指针算术运算

3
int *p=(int*)malloc(sizeof(int)*n);
free(p+n/2);

在上面的代码中,free函数会释放整个数组的后半部分,还是只释放p+n/2这个“单元”?

4
它不会释放任何内容,您必须将最初分配的指针传递给它。 - Ryan
不可以单独释放某个块(通过传递指向该块开头的指针)。 - Alexguitar
通用警告:不要强制转换malloc()的结果! - fuz
5个回答

3

将(p+n/2)这样的表达式传递给free()是不合法的。你只能将从malloc()函数之一返回的指针传递给free()。因此,你必须一次性释放整个数组。


3
传递给free的指针值必须是空指针或先前分配的内存的指针。否则行为未定义(这意味着您的程序可能会崩溃,或者可能会破坏内部运行时数据结构,或者最糟糕的是,它可能会按您的预期行事)。
引用C11标准(草案N1570 7.22.3.3p2):

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


1
最糟糕的是,它可能会按照你的期望运行,直到客户使用你的应用程序,然后一切都会变得一团糟 :-) - gnasher729

2

好的,没错。

如果free()接收到的指针不是由malloc()返回的(NULL指针是唯一的例外,但会导致free()没有效果),则会导致未定义的行为。

你的示例传递了一个指针,但该指针不是由malloc()返回的——尽管它是从该指针计算出来的。

你的示例结果是未定义的行为。

如果你想分配内存并稍后更改已分配的大小,请查阅realloc()


0

你必须只将malloc/calloc/realloc返回的指针传递给free

除了标准规定之外,还有一个特殊的实际原因。 free需要知道分配区域的字节长度。同样,realloc需要知道当前分配区域的字节长度。

在任何这样分配的区域的前面,都有一个隐藏的头结构,用于描述该区域对各种堆函数的使用。例如:

struct memory_descriptor {
    u32 magic;                          // magic number
    size_t length;                      // memory area length in bytes
    struct memory_descriptor *next;     // next memory area
    struct memory_descriptor *prev;     // previous memory area
};

内存块的布局实际上是这样的:

| memory_descriptor | usable memory area ... |
                      ^
                      |
                      + pointer returned by malloc et. al.

当你使用free释放某个东西时,它会取指针并减去描述符大小以定位描述符结构,并使用它来确定内存区域的大小。

如果你传递了像pointer + 10这样的东西,free将无法找到描述符。它将使用那里的任何内容。这就是为什么在这个例子中有一个“魔数字段”来尝试检测这种误用。


在MacOS X上,例如其他实现中,对于小的分配通常看不到这样的头文件。而且没有任何分配的“下一个”和“上一个”。 - gnasher729
@gnasher729 只是一个例子。我已经从头开始编写了一些堆分配。指针可以用于完整性检查。如果您启用它[动态地],则可以双向检查列表并获得更好的损坏信息。没有调试,大小可能足够[带有魔术值]。对于小型分配,它来自子池[可通过地址范围检测],该子池[例如]与页面对齐。您可以向下舍入以找到位图。或者,“2的幂”子池方案与“带外”标头。但是,它们通常需要列表扫描以查找描述固定大小分配块的子池标头。 - Craig Estey

0
在上面的代码中,free函数会释放整个数组的后半部分还是只有p+n/2这个“单元”?
不会,因为在释放时会产生未定义的行为。由于malloc返回内存位置的起始地址,您可以使用该指针作为引用来访问分配的所有内存位置。
您只能释放由malloc分配的指针,如果您尝试从free函数内部释放中间的指针,则会出现无效指针的错误。

free(): invalid pointer:

或者您可以像其他人建议的那样使用realloc,如果您想修改内存的大小,这是最好的选择。

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