使用malloc(0)和memcpy

时间:2014-07-13 21:26:33

标签: c malloc undefined-behavior

我在某处读到:取消引用由大小为零的“新”分配返回的指针是UB。 在C中是否相同? 如果是,是以下代码UB? (假设大小= 0)

 a->object[index].data = malloc(size);  
 memcpy(a->object[index].data, bytes, size);

根据我的理解:不。只是想仔细检查。

3 个答案:

答案 0 :(得分:9)

当您将0作为参数传递给malloc,然后将free分配的内存传递给malloc返回的指针。

结果是实现定义的。

C11:7.22.3内存管理功能:

  

[...]如果请求的空间大小为零,行为是实现定义的:返回空指针,或者行为就像大小是非零的一样值,但返回的指针不得用于访问对象。

另外标准说:

  

free函数导致ptr指向的空间被释放,即可用于进一步分配。 如果ptr是空指针,则不会执行任何操作

因此,在实现定义行为的任​​何一种情况下,释放都不会调用未定义的行为。

现在转到问题的另一部分。

7.1.4库函数的使用:

  

如果函数的参数具有无效值(例如值)   在函数域之外,或者程序地址空间之外的指针,   或一个空指针,或指向不可修改的存储时的对应   参数不是const限定的)或函数不期望的类型(提升后)   使用可变数量的参数,行为未定义

C11:7.24.1 p(2):

  

声明为size_t n的参数指定a的数组长度   function,n在调用该函数时可以为零。除非明确说明   否则,在本子条款中对特定函数的描述中,此类调用上的指针参数仍应具有有效值,如7.1.4 中所述。在这样的调用中,找到一个字符的函数找不到,一个比较两个的函数   字符序列返回零,复制字符的函数复制零   字符。

答案 1 :(得分:1)

根据我对当前标准的阅读(或n1570,它的最终公开草案),代码具有未定义的行为:

  

7.24.1字符串函数约定

     
      
  1. 如果声明为size_t n的参数指定函数的数组的长度,则n 在调用时可以为零到那个功能。除非在本子条款中对特定函数的描述中另有明确说明,否则此类调用上的指针参数仍应具有有效值,如7.1.4 中所述。
  2.         

    7.1.4库函数的使用

         
        
    1. 除非在以下详细说明中另有明确说明,否则以下每个陈述都适用:如果函数的参数具有无效值(例如函数域外的值,或者程序地址空间之外的指针,或者空指针,或者当相应参数不是const限定时指向不可修改存储的指针)或者不期望的类型(提升后)具有可变数量参数的函数,行为未定义
    2.   

(强调补充。)

答案 2 :(得分:1)

 size_t size = 0;
 a->object[index].data = malloc(size);  
 memcpy(a->object[index].data, bytes, size);

从技术上讲,它是未定义的行为。

malloc可能返回空指针以分配零字节,并将空指针传递给memcpy是未定义的行为(即使第三个参数是0)。

来自强大的C标准(强调我的):

  

(C99,7.1.4p1)“[......]除非另有明确说明           以下详细说明:如果是a的参数           函数具有无效值(例如,值之外的值)           函数的域,或地址空间外的指针           程序,或空指针,或指向           当相应参数为时,不可修改的存储           不符合限定条件)或类型(促销后)不期望           通过具有可变数量的参数的函数,行为           未定义