我在某处读到:取消引用由大小为零的“新”分配返回的指针是UB。 在C中是否相同? 如果是,是以下代码UB? (假设大小= 0)
a->object[index].data = malloc(size);
memcpy(a->object[index].data, bytes, size);
根据我的理解:不。只是想仔细检查。
答案 0 :(得分:9)
当您将 0
作为参数传递给malloc
,然后将free
分配的内存传递给malloc
返回的指针。
结果是实现定义的。
[...]如果请求的空间大小为零,行为是实现定义的:返回空指针,或者行为就像大小是非零的一样值,但返回的指针不得用于访问对象。
另外标准说:
free
函数导致ptr
指向的空间被释放,即可用于进一步分配。 如果ptr
是空指针,则不会执行任何操作。
因此,在实现定义行为的任何一种情况下,释放都不会调用未定义的行为。
现在转到问题的另一部分。
如果函数的参数具有无效值(例如值) 在函数域之外,或者程序地址空间之外的指针, 或一个空指针,或指向不可修改的存储时的对应 参数不是const限定的)或函数不期望的类型(提升后) 使用可变数量的参数,行为未定义。
声明为
size_t n
的参数指定a的数组长度 function,n在调用该函数时可以为零。除非明确说明 否则,在本子条款中对特定函数的描述中,此类调用上的指针参数仍应具有有效值,如7.1.4 中所述。在这样的调用中,找到一个字符的函数找不到,一个比较两个的函数 字符序列返回零,复制字符的函数复制零 字符。
答案 1 :(得分:1)
根据我对当前标准的阅读(或n1570,它的最终公开草案),代码具有未定义的行为:
7.24.1字符串函数约定
- 如果声明为
醇>size_t n
的参数指定函数的数组的长度,则n
在调用时可以为零到那个功能。除非在本子条款中对特定函数的描述中另有明确说明,否则此类调用上的指针参数仍应具有有效值,如7.1.4 中所述。7.1.4库函数的使用
- 除非在以下详细说明中另有明确说明,否则以下每个陈述都适用:如果函数的参数具有无效值(例如函数域外的值,或者程序地址空间之外的指针,或者空指针,或者当相应参数不是const限定时指向不可修改存储的指针)或者不期望的类型(提升后)具有可变数量参数的函数,行为未定义。
醇>
(强调补充。)
答案 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的参数 函数具有无效值(例如,值之外的值) 函数的域,或地址空间外的指针 程序,或空指针,或指向 当相应参数为时,不可修改的存储 不符合限定条件)或类型(促销后)不期望 通过具有可变数量的参数的函数,行为 未定义“