解除引用malloc(0)

oli*_*rsm -1 c malloc

malloc(0)C11标准中的行为引用以下*:

void*malloc(size_t size);


如果size为零,则行为是实现定义的(可能返回空指针,或者可能返回一些非空指针,这些指针可能不用于访问存储,但必须传递给free).


*(引自cppreference.com而不是官方的ISO/IEC 9899:2011标准,因为前者需要购买.)

有了这个定义,我就不会期望以下工作(用icc18.0.0 编译):

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    double *u = malloc(0);
    u[0] = 3.0;
    printf("The value of u[0] is %lf", u[0]);
    free(u);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是它起作用并给出了输出:

The value of u[0] is 3.000000
Process finished with exit code 0
Run Code Online (Sandbox Code Playgroud)

它似乎u[0] = 3.0;访问存储.如果malloc返回NULL,则会导致分段错误.

我是否误解了访问存储的概念,或者是否还有其他事情发生?

更新/澄清

似乎我的问题的关键在于" 可能不会用于访问存储 " 的措辞,以及"可能不"意味着不应该不能.我已经读过这个意思,无论指针返回什么都无法解除引用(除非realloc'd).

我已经找到了答案,我可以使用更多的内存,而不是我用malloc()分配的内容,为什么?非常适用于这个问题.主要的一点是,在分配的内存之外写入是未定义的行为,虽然这无疑是错误的,但不能保证抛出和错误.

问题是什么意思malloc(0)有几个答案提到返回的指针.

Ste*_*mit 6

你打电话malloc询问了一个指向某个内存的指针,你可以存储一些数据.您承诺在那里存储的数据不超过0个字节.然后你作弊,或打破了规则,并sizeof(double)在那里存储了字节数.

也许你预料到,既然你违反了规则,一些不好的事情就会出错.但事实证明,写一个malloc指针而不是你所允许的是一个未定义行为的例子,这意味着任何事情 - 绝对是任何事情 - 都可能发生.并且,至关重要的是,可能发生的事情之一是您的程序似乎可以工作,即使它不是"应该"的.

这有点像这样:假设你在半夜沿着一条荒芜的街道行驶,你就会发出红光.由于没有交叉路口,周围没有其他人,当然也没有警察,你决定欺骗并开车穿过十字路口而不等待灯变绿.但是这是什么?没有车撞到你身上.你不要割下任何行人.没有警察给你一张票.怎么会这样?跑红灯是错的,对吧?

嗯,当然,这并不奇怪.你已经观察到没有交叉路口,没有行人,也没有警察.但是,如果这些事情中的任何一件突然出现在最后一刻并且出现一次意外或不舒服的警察采访,那么你本来就错了.

情况与您的代码相同.你有"幸运",并没有什么明显是错误-但代码错误的.

未定义的行为很棘手,很难想到.但是要理解它的一件大事是,它通常不会让你得到错误消息.事实上,未定义行为定义的一个方面是编译器要求给你关于它的任何错误消息.

如果您很好奇,请在此答案中查看有关未定义行为的更多信息.


use*_*738 5

那么你正在处理未定义的行为.你应该清楚这一点.

无论什么,它都不会分配任何内存,你可以放任何东西(就像你在这里做的那样).

和提防NULL支票将无法在这里工作-因为它可能会返回NULL当您传递0malloc.

甚至建议每当你传递一些值malloc然后检查它是否是非零正整数.如果它0不调用malloc- 它没有任何用处.