几年前,CERT发布了一份关于某些编译器的建议,这些编译器优化了C标准中技术上未定义的指针溢出检查,例如:
/* note: not the code being asked about */
#include <stdint.h>
void fn(uint32_t len) {
char buffer[BUFLEN];
if (buffer + len > buffer) { /* not defined if len > BUFLEN! */
die();
}
/* do whatever */
}
在咨询C99标准之后,我现在想知道是否以下代码是明确定义的:
#include <stdlib.h>
#include <stdint.h>
int main() {
uint32_t *buf = malloc(sizeof(uint32_t) * 20);
*(buf+10) = 100;
return *(buf+10);
}
C99标准的相关部分似乎是6.5.6/7
,6.5.6/8
和7.20.3.3/2
。我对该标准的阅读表明如下:
7.20.3.3/2
未表明malloc
分配的内存被视为数组(cf 7.20.3.1
calloc
)。6.5.6/7
,在一个加法表达式中,指向不是数组元素的对象的指针与指向长度为1的数组的第一个元素的指针的行为相同。6.5.6/8
未定义添加表达式的结果,该表达式将指向一个元素,该元素超过数组对象的最后一个元素。由于6.5.6/7
表示在此附加表达式中buf
的行为与指向长度为1的数组的指针相同,因此buf+10
未定义。这是否意味着上面的第二个代码列表是根据C99标准未定义的?
答案 0 :(得分:1)
从7.20.3开始:
如果分配成功,则返回指针,以便可以将其分配给指向任何类型对象的指针,然后用于访问此类对象或此类对象的数组分配空间(直到空间被明确释放。)
(强调我的。)所以我认为你对“malloc会给你一个数组”的部分没问题,一旦你有了,那么其余部分就会出现。