修复了对类型化指针的解引用会破坏严格混叠的问题 [英] Fix for dereferencing type-punned pointer will break strict-aliasing
问题描述
我正在尝试使用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.
别名规则只是说,您只能通过对象自己的类型,其有符号/无符号变体类型或字符类型(char
,signed char
,unsigned 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.
这违反了别名规则,因为您仅有权通过char
,signed char
或unsigned 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_buf
的char
元素,因此这是一个别名冲突.
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屋!