Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
解引用malloc(0)_C_Malloc - Fatal编程技术网

解引用malloc(0)

解引用malloc(0),c,malloc,C,Malloc,C11标准中的行为引用了以下*: void*malloc(大小) 如果大小为零,则行为由实现定义(可以返回空指针,或返回一些非空指针,这些指针可能不用于访问存储,但必须传递给free) *(引用自而非官方ISO/IEC 9899:2011标准,如下所示。) 根据这一定义,我不希望以下内容起作用(使用icc18.0.0编译): 它似乎u[0]=3.0访问存储器。Hadmalloc反而返回了NULL,这将导致分段错误 我是否误解了访问存储的概念,或者是否发生了其他事情 更新/澄清 我的问题的关键

C11标准中的行为引用了以下*:

void*malloc(大小)


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


*(引用自而非官方ISO/IEC 9899:2011标准,如下所示。)

根据这一定义,我不希望以下内容起作用(使用
icc
18.0.0编译):

它似乎
u[0]=3.0访问存储器。Had
malloc
反而返回了
NULL
,这将导致分段错误

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

更新/澄清

我的问题的关键似乎在于“可能不用于访问存储”的措辞,以及“可能不”是否意味着不应该或不能。我认为这意味着无论返回什么指针都不能被取消引用(除非
realloc
'd)

我发现这个问题的答案非常适用于这个问题。主要的一点是,在分配的内存之外进行写入是一种未定义的行为,虽然这无疑是错误的,但不能保证抛出和出错

这个问题有几个答案,提到返回的指针

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

无论发生什么,它都不会将任何内存分配给您可以放置任何东西的位置(就像您在这里所做的那样)

注意
NULL
检查在这里不起作用-因为当您将
0
传递到
malloc
时,它可能会返回
NULL

甚至有人建议,无论何时向
malloc
传递某个值,都要检查该值是否为非零正整数。如果它是
0
不要调用
malloc
-它没有任何用处。

语句

double *u = malloc(0);
使程序的行为依赖于语句执行时的实现

u[0] = 3.0;
当然调用未定义的行为,因为标准明确规定返回指针不应用于访问对象。因此,您不能通过
malloc(0)
取消对指针返回的引用

§7.22.3(p1):

[…]但返回的指针不得用于访问对象


您调用了
malloc
,要求提供一个指向某个内存的指针,您可以在该内存中存储一些数据。您承诺在那里存储的数据不超过0字节。然后你作弊,或者违反了规则,而是在那里存储了
sizeof(double)
字节数

也许你预料到了,既然你违反了规则,那么一些糟糕而明显的事情就会出错。但事实证明,向malloc'ed指针写入超出允许范围的内容是未定义行为的一个例子,这意味着任何事情——绝对任何事情——都可能发生。而且,至关重要的是,可能发生的事情之一是,您的程序似乎可以工作,即使它不是“应该”工作的

这有点像:假设你在半夜里沿着一条废弃的街道开车,你就闯红灯了。由于没有交叉路口,周围没有其他人,当然也没有警察,你决定作弊,在不等待绿灯变绿的情况下驾车通过十字路口。但这是什么?没有汽车撞到你。你不会撞倒任何行人。没有警察给你开罚单。这怎么可能?闯红灯是不对的,对吗

当然,这并不奇怪。你已经注意到这里没有交叉路口,没有行人,也没有警察。但是,如果这些事情中的任何一件在最后一刻突然出现,并且发生了事故或令人不安的警方采访,那么你就大错特错了

代码的情况也是如此。你很幸运,没有什么明显的问题,但代码是错的

未定义的行为很棘手,很难思考。但需要了解的一件大事是,它不是您通常可以期望得到错误消息的东西。事实上,未定义行为的一个定义方面是编译器不需要向您提供任何有关它的错误消息


如果您感到好奇,请在上查看有关未定义行为的更多信息。

正如其他答案向您解释的那样,该行为是。你应该是

顺便说一句,您可以添加一些
printf(“u是%p\n”,(void*)u)在您的
malloc
之后

然而,在我的Linux/Debian系统上,
malloc
主要由实现,它通常是GNU(但也可以是其他的东西,比如)并且是。您可以查看glibc的文件并了解
malloc(0)
提供了一些有效的指针。有关musl libc,请参见其文件


FWIW,编译器主要通过for了解
malloc
,因此,

未定义的行为是。。。好。。。未定义。我很想知道Valgrind在你使用它运行这个程序时告诉了你什么。C编译器大多遵循一种相当无政府主义的方法,他们只是让你做你认为正确的事情,至少如果可能的话,即使它不被任何规则所允许,有时,惊讶,惊讶,它似乎仍然有效…;-)C11标准实际上与可自由下载的标准相同。您不需要指定是哪种标准,但还应该注意,根据您是为发布还是调试而构建,这些行为可能会有很大的差异。很多时候,在一个调试版本上运行一百次的东西会在发布版本中停止并着火。
double *u = malloc(0);
u[0] = 3.0;