我一直在阅读有关malloc
请求零大小的块时的行为的讨论。
我理解malloc(0)
的行为是实现定义的,它应该返回一个空指针,或一个非空指针,我仍然不应该访问。 (这是有道理的,因为它不能保证它指向任何可用的内存。)
但是,如果获得这样一个不可访问的非空指针,我是否可以通常的方式将其传递给free
?或者这是非法的,因为我从malloc(0)
获得的指针可能不指向实际分配的内存块?
具体而言,以下代码是否具有明确定义的行为:
#include <stdio.h>
#include <stdlib.h>
int main() {
int* x = (int*) malloc(0);
if (x == NULL) {
printf("Got NULL\n");
return 0;
} else {
printf("Got nonnull %p\n", x);
}
free(x); // is calling `free` here okay?
}
答案 0 :(得分:42)
C99标准(实际上是WG14 / N1124。委员会草案 - 2005年5月6日.ISO / IEC 9899:TC2)说malloc()
:
返回的指针指向开始(最低字节 地址)分配的空间。如果无法分配空间,则为空指针 回。如果请求的空间大小为零,则行为是实现定义的: 返回空指针,或者行为就像大小一样 非零值,但返回的指针不得用于访问对象
和约free()
:
否则,如果 该参数与之前由calloc,malloc或realloc函数返回的指针不匹配,或者如果通过调用free或realloc释放了该空间,则该行为未定义。
IEEE Std 1003.1-2008(POSIX),2016年版关于free()
:
free()函数将导致ptr指向的空间 释放;也就是说,可供进一步分配。如果是ptr 空指针,不会发生任何动作。否则,如果参数确实如此 不匹配POSIX.1-2008中函数返回的指针 像malloc()一样分配内存,或者空间如何 通过调用free()或realloc()解除分配,行为是 未定义。
因此,无论*alloc()
返回什么,您都可以转到free()
。
至于malloc()
的当前实施:
FreeBSD使用提供的jemalloc
void *
je_malloc(size_t size)
{
void *ret;
size_t usize JEMALLOC_CC_SILENCE_INIT(0);
if (size == 0)
size = 1;
[...]
而Apple的libmalloc确实
void *
szone_memalign(szone_t *szone, size_t alignment, size_t size)
{
if (size == 0) {
size = 1; // Ensures we'll return an aligned free()-able pointer
[...]
GLIBC也改变了要求的尺寸;它正在使用所请求的大小(以字节为单位)调用此宏作为参数,以将大小与特定边界对齐,或者只是最小分配大小:
#define request2size(req) \
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
MINSIZE : \
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
答案 1 :(得分:25)
是的,实际上你必须这样做以避免可能的内存泄漏。
malloc系统通常在指针之前的空间中返回一个隐藏的控制块,其中包含分配大小等信息。如果分配大小为零,则此块仍然存在并占用内存,如果malloc返回非null。