【发布时间】:2017-05-02 11:20:45
【问题描述】:
坦率地说,这样的代码是有效的还是会产生 UB?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct __attribute__((__packed__)) weird_struct
{
int some;
unsigned char value[1];
};
int main(void)
{
unsigned char text[] = "Allie has a cat";
struct weird_struct *ws =
malloc(sizeof(struct weird_struct) + sizeof(text) - 1);
ws->some = 5;
strcpy(ws->value, text);
printf("some = %d, value = %s\n", ws->some, ws->value);
free(ws);
return 0;
}
我从不认为它对这样的事情有效,但 SystemV 消息队列似乎正是这样做的:see the man page。
那么,如果 SysV 消息队列可以做到这一点,也许我也可以做到这一点?我想我会发现这对通过网络发送数据很有用(因此是 __attribute__((__packed__)))。
或者,也许这是 SysV 消息队列的特定保证,我不应该在其他地方做类似的事情?或者,也许可以使用这种技术,只是我做错了?我想我最好问问。
malloc(sizeof(struct weird_struct) + sizeof(text) - 1) 中的这个- 1 是因为我考虑到由于unsigned char value[1] 无论如何都会分配一个字节,所以我可以从sizeof(text) 中减去它。
【问题讨论】:
-
@IharobAlAsimi 因为
sizeof(struct weird_struct)中计算了一个字节,因为unsigned char value[1]的大小无论如何都是一个字节?至少我是这么想的。 -
@IharobAlAsimi,看起来确实如此。虽然我同意您使用
strlen()的建议。 -
访问超出其声明限制的数组会调用未定义的行为。它适用于大多数编译器,但使用灵活的数组成员编译器可能会更严格地处理它;不要依赖上面的代码来工作。
-
@Olaf 因此,我认为 POSIX 必须 规定这不是 UB,否则如果不调用 POSIX 提到的 SysV msg 队列,就不可能UB?这是正确的吗?
-
原始
arr[1]struct hack 是否会引发UB,当结构分配时没有声明类型(例如通过malloc),取决于“对象”一词的确切含义C标准,从来没有得到任何人满意的解决;尽管不断尝试修正措辞,但案文仍然自相矛盾,并且仍然至少有三种解释具有很强的“预期”含义;在其中两个之下是 UB,但在第三个之下不是。
标签: c arrays language-lawyer undefined-behavior flexible-array-member