POSIX打算指向struct sockaddr
的变体,但是根据C标准的解释,这可能违反了严格的别名规则,因此违反了UB。 (见this answer与它下面的评论。)我可以,至少,在确认不存在至少可以用gcc的一个问题:这个代码打印Bug!
与优化启用,Yay!
与优化禁用:如何在不违反严格别名规则的情况下合法地使用类型捣破与工会在struct sockaddr的变体之间进行投射?
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
sa_family_t test(struct sockaddr *a, struct sockaddr_in *b)
{
a->sa_family = AF_UNSPEC;
b->sin_family = AF_INET;
return a->sa_family; // AF_INET please!
}
int main(void)
{
struct sockaddr addr;
sa_family_t x = test(&addr, (struct sockaddr_in*)&addr);
if(x == AF_INET)
printf("Yay!\n");
else if(x == AF_UNSPEC)
printf("Bug!\n");
return 0;
}
观察这行为在online IDE。
要解决这一问题this answer提出与工会的使用类型双关的:
/*! Multi-family socket end-point address. */
typedef union address
{
struct sockaddr sa;
struct sockaddr_in sa_in;
struct sockaddr_in6 sa_in6;
struct sockaddr_storage sa_stor;
}
address_t;
然而,显然事情仍然并不像看起来那么简单......由@zwol报价this comment:
那可以工作,但需要一定的照顾。超过我可以适应这个评论框。
什么样的公平的照顾这是否需要?使用类型捻与工会在struct sockaddr
变体之间施加什么缺陷?
我更愿意问,而不是碰到UB。
目前还不清楚你的“联盟”的实际问题是什么。 [mcve]和你关心的更多细节如何?你为什么不问zwol他的意思?我们不是千里眼。 – Olaf
@Olaf为什么不问zwol?因为正如我引用他的话,他已经表示,他不想在评论中谈论这一点。一个最小,完整和可验证的例子呢?嗯,我正在问这个问题,因为我想避免陷入我未知的陷阱,这将使我有必要制作这样一个最小化,完整和可验证的示例。当谈到C的UB时,我认为“更好的防止而非治疗”这个词完全成立。 – gaazkam
我不确定如果不修改涉及sockaddr的所有接口,就可以做任何事情。不管你现在的函数是什么,仍然期望struct sockaddr *而不是任何类型的联合。 –