int *p=(int*)malloc(sizeof(int)*n);
free(p+n/2);
在上面的代码中,free函数会释放整个数组的后半部分,还是只释放p+n/2这个“单元”?
int *p=(int*)malloc(sizeof(int)*n);
free(p+n/2);
将(p+n/2)这样的表达式传递给free()
是不合法的。你只能将从malloc()
函数之一返回的指针传递给free()
。因此,你必须一次性释放整个数组。
free
的指针值必须是空指针或先前分配的内存的指针。否则行为未定义(这意味着您的程序可能会崩溃,或者可能会破坏内部运行时数据结构,或者最糟糕的是,它可能会按您的预期行事)。
free
函数导致由ptr
指向的空间被释放,即可供进一步分配。如果ptr
是空指针,则不执行任何操作。否则,如果参数与先前由内存管理函数返回的指针不匹配,或者如果该空间已通过调用free
或realloc
进行了释放,则行为未定义。
好的,没错。
如果free()
接收到的指针不是由malloc()
返回的(NULL指针是唯一的例外,但会导致free()
没有效果),则会导致未定义的行为。
你的示例传递了一个指针,但该指针不是由malloc()
返回的——尽管它是从该指针计算出来的。
你的示例结果是未定义的行为。
如果你想分配内存并稍后更改已分配的大小,请查阅realloc()
。
你必须只将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
将无法找到描述符。它将使用那里的任何内容。这就是为什么在这个例子中有一个“魔数字段”来尝试检测这种误用。
或者您可以像其他人建议的那样使用realloc,如果您想修改内存的大小,这是最好的选择。free(): invalid pointer:
malloc()
的结果! - fuz