保证执行memcpy(0,0,0)是否安全?

时间:2011-03-09 08:17:55

标签: c memcpy language-lawyer null-pointer

我不太熟悉C标准,所以请耐心等待。

我想知道,按标准保证memcpy(0,0,0)是否安全。

我能找到的唯一限制是,如果内存区域重叠,那么行为是未定义的......

但我们可以考虑内存区域在这里重叠吗?

3 个答案:

答案 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指针的反应还不确定。