https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90186
--- Comment #2 from austin.card at torchtechnologies dot com ---
(In reply to Richard Biener from comment #1)
> Note that using #pragma pack(1) on struct Ipv4 makes u_short members not
> naturally aligned and thus code like
>
> void UpdateChecksum()
> {
> u_long sum(0);
>
> SetChecksum(0);
>
> u_short *buf = (u_short*)ip->Payload();
> u_long nwords = ip->PayloadSize() / 2;
>
> for (unsigned i = 0; i < nwords; ++i)
> {
>
> sum += ntohs(*buf++);
>
> dereferences pointers to u_short that might not be aligned to a 2 byte
> boundary.
>
> Confirmed though, even when using -fno-inline. -fno-strict-aliasing fixes
> it. Possibly the very same issue above - using u_short * to access memory
> with a different dynamic type. The same happens here:
>
> buf = (u_short*)&ph;
> nwords = 6;
>
> for (unsigned i = 0; i < nwords; ++i)
> {
>
> sum += ntohs(*buf++);
>
> ph is of type PseudoHeader. You cannot use lvalues of type u_short to
> refer to them.
So if this is an alignment issue, How does the #pragma pack(1) change the
alignment differently between option -O1 and -O2? Also in Udp.h if I uncomment
the dummy function at line 147, then the code produces the same output between
-O1 and -O2.
I have tried to produce the same result with other compilers:
clang++ -std=c+11 -O2 -o CheckSum main.cpp CheckSum.cpp
clang++ -std=c+11 -O1 -o CheckSum main.cpp CheckSum.cpp
does not have this problem.
And Microsoft VS2017 compiler does not have this problem between Debug and
Release.
Lastly, the code provided is computing the 16-bit checksum of a UDP packet
header contained in an IPv4 network packet. While the comment regarding
alignment of u_short members is in general correct, any misaligned members are
intended by the RFC standards.