使用malloced内存未定义写入前读取?

时间:2012-02-09 22:36:34

标签: c undefined-behavior language-lawyer initialization

根据this reddit comment thread,如果在写入内存之前尝试读取内存,则未定义。我指的是正常的堆内存,它已成功malloc编辑。

  

...请注意,这不是严格有效的C:允许编译器/运行时系统使用所谓的陷阱表示来初始化未初始化的内存,这会导致访问时出现未定义的行为。

我觉得很难相信。有标准报价吗?

当然,我知道无法保证内存已被清零。这个未初始化的存储器中的值基本上是伪随机的或任意的。但我真的不相信标准会将此称为未定义的行为(从某种意义上说它可能是段错误,或者删除所有文件,或者其他什么)。其余的reddit主题并没有对这个问题有所了解。

3 个答案:

答案 0 :(得分:11)

如果通过char*进行访问,则会定义此内容。但除此之外,这是未定义的行为。

  

(C99,7.20.3.3)“malloc函数为大小由大小指定且其值不确定的对象分配空间。”

关于不确定值:

  

(C99,3.17.2p1)“不确定值:未指定的值或陷阱表示”

在陷阱表示中读取非字符类型是未定义的行为:

  

(C99,6.2.6.1p5)“某些对象表示不需要表示对象类型的值。如果对象的存储值具有这样的表示,并且由不具有字符类型的左值表达式读取,行为是未定义的。[...]这种表示称为陷阱表示。“

答案 1 :(得分:3)

理性上必须不明确。否则,在Valgrind之下运行的C程序的必要行为,它会诊断未初始化内存的读取并在发生时发出适当的错误,在标准下是非法的。

阅读标准,关键问题是malloc内存的值是“未指定值”(必须是一些可读值),还是“不确定值”(可能包含陷阱表示;参见定义3.17.2) 。)

根据7.20.3.3,在其他答案中引用,malloc返回一个包含不确定值的内存块,因此可能包含陷阱表示。陷阱表示的相关讨论是6.2.6.1,第5部分:

  

某些对象表示不需要表示对象类型的值。如果对象的存储值具有这样的表示并且由不具有字符类型的左值表达式读取,则行为是未定义的。 ......这种表示称为陷阱表示

所以,你去吧。基本上,C实现被允许检测(即“陷阱”)对不确定值的引用,并处理它选择的错误,包括以未定义的方式。

答案 2 :(得分:2)

ISO/IEC 9899:1999,7.20.3.3 malloc函数:

  

malloc函数为一个对象分配空间,该对象的大小由size和   其价值是不确定的。

6.2.6.1类型的表示,§5:

  

某些对象表示不需要表示对象类型的值。如果存储   对象的值具有这样的表示,并由左值表达式读取   没有字符类型,行为是未定义的。

脚注41使其更加明确(至少对于自动变量):

  

因此,可以将自动变量初始化为陷阱表示而不会导致未定义的行为,但只有在其中存储了正确的值之后才能使用该变量的值。