我不太熟悉C标准,所以请耐心等待。
我想知道,按标准保证memcpy(0,0,0)
是否安全。
我能找到的唯一限制是,如果内存区域重叠,那么行为是未定义的......
但我们可以考虑内存区域在这里重叠吗?
答案 0 :(得分:67)
我有C标准的草案版本(ISO / IEC 9899:1999),它有一些有趣的事情可以说。对于初学者,它提到(§7.21.1/ 2)关于memcpy
声明为
size_t
n的参数指定a的数组长度 function,n在调用该函数时可以为零。除非明确说明 否则在本子条款中特定功能的描述中,指针参数 如此调用仍应具有有效值,如7.1.4 中所述。在这样的电话中,a 找到一个字符的函数找不到,一个比较两个的函数 字符序列返回零,复制字符的函数复制零 字符。
此处指出的参考文献指出:
如果函数的参数具有无效值(例如值) 在函数域之外,或者程序地址空间之外的指针, 或空指针,或指向不可修改的存储时对应的 参数不是const限定的)或函数不期望的类型(提升后) 如果参数数量可变,行为未定义。
所以看起来根据C规范,调用
memcpy(0, 0, 0)
会导致未定义的行为,因为空指针被视为“无效值”。
那就是说,如果你这样做,memcpy
的任何实际实现都会破坏,我会感到非常惊讶,因为如果你说复制零字节,我能想到的大部分直观实现都不会做任何事情。
答案 1 :(得分:21)
只是为了好玩,gcc-4.9的发布说明表明它的优化器使用了这些规则,例如可以删除条件
int copy (int* dest, int* src, size_t nbytes) {
memmove (dest, src, nbytes);
if (src != NULL)
return *src;
return 0;
}
然后在调用copy(0,0,0)
时会产生意外结果(请参阅https://gcc.gnu.org/gcc-4.9/porting_to.html)。
我对gcc-4.9的行为有些矛盾;行为可能符合标准,但能够调用memmove(0,0,0)有时是对这些标准的有用扩展。
答案 2 :(得分:-2)
否,memcpy(0,0,0)
不安全。标准库可能不会在该调用上失败。但是,在测试环境中,memcpy()中可能存在一些额外的代码,以检测缓冲区溢出和其他问题。那个特殊版本的memcpy()对NULL指针的反应还不确定。