Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
496 views
in Technique[技术] by (71.8m points)

c - Fix for dereferencing type-punned pointer will break strict-aliasing

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

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

and the two culprits are:

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

and

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

incoming_buf and outgoing_buf are defined as follows:

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

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 says violating aliasing rules invokes undefined behavior (so don't!).

In this line of your program:

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

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.

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);

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

Proposed solution

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)];

(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).

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;

or

char_lvalue = *((char *) incoming_buf);

EDIT:

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...