ano*_*nol 15 c malloc language-lawyer
我试图说服(引用C99标准的具体部分)一位同事,以下是未定义的行为:
int *p = malloc(1);
p[0] = 0;
Run Code Online (Sandbox Code Playgroud)
但我无法在标准中找到明确确保未定义的具体部分.我正在寻找标准中从这些线到结论的逻辑步骤:未定义的行为.它是从第一行转换void *
到int *
第一行吗?第二行的作业?
我能找到的唯一相关部分malloc
是它返回一个适当对齐的指针(7.20.3):
如果分配成功,则返回指针,以便将其分配给指向任何类型对象的指针,然后用于在分配的空间中访问此类对象或此类对象的数组(...)
我试着在标准中寻找空间,但是由于空白和其他词汇问题,噪音太大了.
Moh*_*ain 18
从7.20.3.3添加malloc函数到你的引用:
malloc函数为一个对象分配空间,该对象的大小由size指定,其值是不确定的.
malloc函数返回空指针或指向已分配空间的指针.
所以有两种可能的未定义行为来源,一种是覆盖(int的大小保证是16位或更多,但是你只分配1个字节,几乎所有系统都是8位)缓冲区,第二种可能是de - 引用空指针.
从6.5.2.1数组下标,p[0] = 0
相当于*p = 0
.类型*p
是一个int
所以它将填充sizeof(*p) * CHAR_BIT
位0
,可能不是所有都属于分配的缓冲区导致UB.
在第一行代码(赋值)中没有未定义的行为,如果任何行将在第二行(取消引用),则UB.
但是,在一些机器上CHAR_BIT
是大sizeof(int)
是1
,这将是良好定义的行为时,情况malloc
并没有return
一个空指针.
int *p = malloc(1);
p[0] = 0;
Run Code Online (Sandbox Code Playgroud)
这是未定义的行为,因为您已经分配了1个字节,并且在上面的赋值中,您尝试写入4个字节(假设int
是4个字节).这只适用于sizeof(int) > 1
.
...
语义
一元&运算符产生其操作数的地址.如果操作数具有类型''type'',则结果具有类型''指向类型''的指针.如果操作数是一元*运算符的结果,则不会对该运算符和&运算符进行求值,结果就好像两者都被省略,除了对运算符的约束仍然适用且结果不是左值.类似地,如果操作数是[]运算符的结果,则[]运算符和[]所暗示的一元*都不会被计算,结果就像删除了&运算符并且[]运算符被更改为a +运算符.否则,结果是指向由其操作数指定的对象或函数的指针.
一元*运算符表示间接.如果操作数指向函数,则结果是函数指示符; 如果它指向一个对象,则结果是指定该对象的左值.如果操作数的类型为''指向类型'',则结果的类型为''type''.如果为指针分配了无效值,则unary*运算符的行为未定义.
该[]
运营商是一个隐含*
的指针操作.分配给该指针的值是无效的用于int
只要sizeof( int ) > 1
.
行为未定义.
并且NULL
是一个无效的指针,所以这也包括malloc()
返回NULL
.
标准引用:
J.2,未定义的行为:在以下情况下,行为未定义:...数组下标超出范围,即使某个对象显然可以使用给定的下标访问
6.2.5,类型,20:数组类型描述了连续分配的非空对象集.
只要sizeof(int) > 1
您malloc(1)
没有分配一组非空对象,那么分配的数组大小为零,并且p[0]
您使用超出范围的下标进行访问.QED.