0

对于套接字编程,有两种处理地址的基本结构:struct sockaddr_insockaddr。根据man的说法,“这个结构 [ sockadrr ] 的唯一目的是转换在 addr 中传递的结构指针,以避免编译器警告”每个手册、书籍或程序员上的代码片段都会假设一个函数需要一个 struct sockaddr * 您可以轻松安全地将 struct sockaddr_in* 转换为该类型。

来自 man 绑定的示例

struct sockaddr_in myaddr;
int s;

myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(3490);
inet_aton("63.161.169.137", &myaddr.sin_addr.s_addr);

s = socket(PF_INET, SOCK_STREAM, 0);
bind(s, (struct sockaddr*)&myaddr, sizeof(myaddr));

问题是这种转换违反了 MISRA C++ 2008 规则 5-2-7 违规:具有指针类型的对象不应直接或间接转换为不相关的指针类型。

我想知道的是,为了克服这个问题(我相信有很多人在使用套接字和 MISRA)总是有必要证明规则的偏差是合理的?实际上没有其他选择吗?

相关问题解释了对 sockaddr 的转换是如何完成的:

套接字编程,将 sockaddr_in 转换为 sockaddr。为什么?

sockaddr 和 sockaddr_in 之间的转换

类型转换 sockaddr 结构

4

3 回答 3

1

如阅读规则 5.2.7 所述,错误来自尝试在不兼容类型之间进行强制转换。它与 C 或 C++ 强制转换无关 - 使用reinterpret_cast同样糟糕。您只是在两种不同的结构类型之间进行可疑的转换,这在 C 和 C++ 中都是未定义的行为。

自从我使用 Windows 套接字以来已经有很长时间了,但据我所知sockaddr,它与sockaddr_in. 我可能弄错了,但似乎该工具只是在说“这里有错误”,而解决方案是修复错误?

否则,如果它们在内存布局方面确实是等效的,那么在 C 中,您可以通过创建union两种结构类型中的一种来解决这个问题,初始化一种类型并将另一种类型传递给函数,也称为“类型双关”。但是,这在 C++ 中是不允许的。请注意,winsock 是为 C 而不是 C++ 设计的。

C++ 解决方案意味着您要么必须将memcpy一个结构实例放入另一个(相当可疑的做法),要么编写一些序列化/反序列化例程(慢)。

或者您可以只使用函数要求的实际类型,所有问题都会消失......

于 2021-09-22T12:52:56.887 回答
0

根据我对这种代码的经验(也在 MISRA 上下文中):只需向 linter 添加适当的异常并继续执行。这种类型的转换需求通常是每个程序员都偶然发现的套接字 API 中的一个设计缺陷,并且没有什么可以避免它(如果有的话)。

可以(并且可能应该)做的是限制这些转换的数量,并且只在传递给套接字特定的 API 函数时进行转换,永远不会更早;反过来,这将通过将它们抽象为一种解决方法来限制套接字 API 调用的数量。但是,仍然无法避免类型转换,只能(并且应该)限制它们的数量和范围。

于 2021-09-25T09:03:19.597 回答
0

来自 man 绑定的示例


myaddr.sin_family = AF_INET; myaddr.sin_port = htons(3490);
inet_aton("63.161.169.137", &myaddr.sin_addr.s_addr);

s = socket(PF_INET, SOCK_STREAM, 0); bind(s, (struct
sockaddr*)&myaddr, sizeof(myaddr)); ```

The problem is this casting violates MISRA C++ 2008 Rule 5-2-7
violation: An object with pointer type shall not be converted to an
unrelated pointer type, either directly or indirectly.

正确的。您正在将指针转换为指向struct sockaddr_in的指针struct sockaddr。施法到不相关的类型通常是一件坏事

如果您确实需要这样做,那么您需要提出偏差,不仅要记录您正在这样做,还要详细说明您将执行的缓解措施以证明您的代码适合使用。

于 2021-09-25T08:34:02.667 回答