这是严格别名规则中断的有效代码修复吗?

时间:2015-09-21 01:26:09

标签: c

我想在我的Infiniband ConnectX-3卡上构建/刻录最新的Mellanox Flexboot固件。但是,Mellanox尚未提供二进制形式的最新版本。但他们提供了源代码。

不幸的是,当我尝试编译它时,我收到以下错误:

net/udp/dhcp.c: In function 'start_dhcp':
net/udp/dhcp.c:1361:3: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
   seed += *( ( uint32_t * )&netdev->ll_addr[j] );
   ^
cc1: all warnings being treated as errors
make: *** [bin/dhcp.o] Error 1
make: *** Waiting for unfinished jobs....
Build failed!

查看代码,以下块是问题所在。特别是种子线。这是因为严格的别名已经开启,我们正在尝试将一种类型作为另一种类型进行访问。

/**
 * Having both i and j , makes the code more robust
 * in the improbable case that MAX_LL_ADDR_LEN is not a
 * multiple of 4 bytes.
 */
for ( i = 0, j = 0; i < ( MAX_LL_ADDR_LEN >> 2 ); ++i, j += 4 ){
   seed += *( ( uint32_t * )&netdev->ll_addr[j] );
}

我的修复使它编译。<​​/ p>

for ( i = 0, j = 0; i < ( MAX_LL_ADDR_LEN >> 2 ); ++i, j += 4 ){
   uint32_t s;
   memcpy(&s, &netdev->ll_addr[j], 4);
   seed += s;
}

但在我烧之前,这实际上是等同的吗?我认为应该是这样,但在我烧掉一些非常重要的东西之前,我只是想要第二个意见。

供参考: ll_addr定义为:

#define MAX_LL_ADDR_LEN 20

...

/** Link-layer address
 *
 * This is the current link-layer address assigned to the      
 * device.  It can be changed at runtime.
 */
 uint8_t ll_addr[MAX_LL_ADDR_LEN];

种子后来在这里使用:

 dhcp->xid = random ( seed );

 /* Store DHCP transaction ID for fakedhcp code */
 dhcp_last_xid = dhcp->xid;

因此,在我看来,这个种子的东西只是用来为随机数生成器播种。我不确定他们种下它的方式是不是一个非常好的主意,但是它不应该伤害事情,我认为我的修复应该没问题,即使它给出了不同的答案。所以,谢谢大家的答案。

1 个答案:

答案 0 :(得分:2)

在这种情况下,只要charj的数组,您就是安全的。 uint32_t的增量保证增量一次只执行四个字节,即onError的宽度。

在这种情况下,最好使用原始实现并忽略错误,特别是如果代码是在C99之前编写的。

Lorehead在关于字节序方面也提出了一个很好的观点。