修复了对类型化指针的解引用会破坏严格混叠的问题 [英] Fix for dereferencing type-punned pointer will break strict-aliasing

查看:213
本文介绍了修复了对类型化指针的解引用会破坏严格混叠的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用GCC编译特定程序时修正两个警告.警告是:

I'm trying to fix two warnings when compiling a specific program using GCC. The warnings are:

警告:取消引用类型标记的指针会中断 严格混叠规则[-Wstrict-aliasing]

warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

两个罪魁祸首是:

unsigned int received_size = ntohl (*((unsigned int*)dcc->incoming_buf));

*((unsigned int*)dcc->outgoing_buf) = htonl (dcc->file_confirm_offset);

incoming_buf outgoing_buf 定义如下:

char                    incoming_buf[LIBIRC_DCC_BUFFER_SIZE];

char                    outgoing_buf[LIBIRC_DCC_BUFFER_SIZE];

这似乎与我所研究的警告的其他示例略有不同.我宁愿解决此问题,也不愿禁用严格混叠检查.

This seems subtly different than the other examples of that warning I've been examining. I would prefer to fix the problem rather than disable strict-aliasing checks.

有很多使用工会的建议-在这种情况下什么是合适的工会?

There have been many suggestions to use a union - what might be a suitable union for this case?

推荐答案

首先,让我们检查一下为什么会收到别名冲突警告.

First off, let's examine why you get the aliasing violation warnings.

别名规则只是说,您只能通过对象自己的类型,其有符号/无符号变体类型或字符类型(charsigned charunsigned char ).

Aliasing rules simply say that you can only access an object through its own type, its signed / unsigned variant type, or through a character type (char, signed char, unsigned char).

C说违反别名规则会引起未定义的行为(所以不要!).

C says violating aliasing rules invokes undefined behavior (so don't!).

在程序的这一行:

unsigned int received_size = ntohl (*((unsigned int*)dcc->incoming_buf));

尽管incoming_buf数组的元素的类型为char,但是您以unsigned int的形式访问它们.实际上,表达式*((unsigned int*)dcc->incoming_buf)中的取消引用运算符的结果为unsigned int类型.

although the elements of the incoming_buf array are of type char, you are accessing them as unsigned int. Indeed the result of the dereference operator in the expression *((unsigned int*)dcc->incoming_buf) is of unsigned int type.

这违反了别名规则,因为您仅有权通过charsigned charunsigned char来访问incoming_buf数组的元素(请参见上面的规则摘要!).

This is a violation of the aliasing rules, because you only have the right to access elements of incoming_buf array through (see rules summary above!) char, signed char or unsigned char.

请注意,第二个罪魁祸首是完全相同的别名问题:

Notice you have exactly the same aliasing issue in your second culprit:

*((unsigned int*)dcc->outgoing_buf) = htonl (dcc->file_confirm_offset);

您通过unsigned int访问outgoing_bufchar元素,因此这是一个别名冲突.

You access the char elements of outgoing_buf through unsigned int, so it's an aliasing violation.

建议的解决方案

要解决您的问题,您可以尝试以要访问的类型直接定义数组的元素:

To fix your issue, you could try to have the elements of your arrays directly defined in the type you want to access:

unsigned int incoming_buf[LIBIRC_DCC_BUFFER_SIZE / sizeof (unsigned int)];
unsigned int outgoing_buf[LIBIRC_DCC_BUFFER_SIZE / sizeof (unsigned int)];

(通过unsigned int的宽度定义实现的方式,因此,如果程序假定unsigned int为32位,则应考虑使用uint32_t).

(By the way the width of unsigned int is implementation defined, so you should consider using uint32_t if your program assumes unsigned int is 32-bit).

通过这种方式,您可以通过char类型访问元素,从而将unsigned int对象存储在数组中而不会违反别名规则,如下所示:

This way you could store unsigned int objects in your array without violating the aliasing rules by accessing the element through the type char, like this:

*((char *) outgoing_buf) =  expr_of_type_char;

char_lvalue = *((char *) incoming_buf);


我已经完全修改了答案,特别是解释了为什么程序从编译器中获取别名警告.

I've entirely reworked my answer, in particular I explain why the program gets the aliasing warnings from the compiler.

这篇关于修复了对类型化指针的解引用会破坏严格混叠的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆