当我们使用负参数调用Malloc时会发生什么?

22
7.22.3.4 malloc函数
malloc函数用于分配一个对象的空间,该对象的大小由size参数指定,其值为未确定的。
原型:void *malloc(size_t size);
当我将一个负值作为参数传递时,malloc(negative)返回NULL。
这是因为[size_t]负数被转换为无符号数后变成了[某个大值],并且不能分配所需的空间,还是因为该函数正在检查参数并返回NULL?
如果被转换为了一个大正数,那么调用malloc(INT_MIN+2)仍然返回NULL,但是malloc(0)分配给指针,并且*p=somevalue可以工作。这是怎么回事?
这是否是实现定义的?
请阅读此链接:malloc(0)

size_t 是无符号类型,而 ssize_t 则是有符号类型。 - Alexander Oh
2个回答

29

size_t值总是正数,即使您向malloc传递了负值。这个负值会被转换为size_t类型的无符号值,从而导致一个巨大的正值。

例如:

char *p = malloc(-2);

等同于:

char *p = malloc(SIZE_MAX - 1);  // SIZE_MAX is the maximum
                                 // size_t value 

@spbnick,这实际上不是实现定义的,而是由*(c99, 6.3.1.3p2)规定:“否则,如果新类型是无符号的,则通过反复添加或减去可以在新类型中表示的最大值加一来转换该值,直到该值在新类型的范围内为止”。 - ouah
@ouah 谢谢,我真的应该花时间阅读标准。然而,这不基本上是遮掩高位吗?而且这不基本上意味着将有符号表示解释为无符号表示,并且该表示是实现定义的吗? - spbnick
如果 offset 是一个小正数,那么 INT_MIN + offset 仍然是一个负数。 - ouah
事实上,向 malloc() 传递负值是完全不可能的。任何负参数值都会被隐式转换为 size_t,这是一种无符号类型,因此不能表示负值。 - Keith Thompson
2
假设intsize_t都是32位。如果INT_MIN == -2147483648offset == 100,那么INT_MIN + offset == -2147483548,当转换为32位的size_t时,结果为+2147483748 - Keith Thompson
显示剩余7条评论

8
由于malloc的参数类型是无符号的size_t,但你传递的是带符号的整数,因此整数值将被转换为size_t。这个规则在草案C99标准第6.3.1.3有符号和无符号整数下的转换中有所涵盖,其中提到:

否则,如果新类型是无符号的,则通过重复加上或减去可以在新类型中表示的最大值加一,直到该值在新类型的范围内。49)

让我们看一个例子来解释这意味着什么,如果你传入-1,那么将会加上最大的size_t值+1:

-1 + MAX_SIZE_T + 1

这将导致:
 MAX_SIZE_T

对于 -5,你将得到:
MAX_SIZE_T - 4

这意味着对于小的负值,得到的size_t值将是一个非常大的正数。

那么为什么在这些情况下你会收到mallocNULL返回值?如果我们回到草案标准的第7.20.3内存管理函数中,它说:

如果无法分配空间,则返回空指针。

你正在进行一个过于庞大的请求,无法分配空间。


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