Mu00
Mu00

Reputation: 83

Feature, bug or UB? The expected infinite loop in my code is deleted when using gcc -O2

The code is the following:

#include <cstdint>
#include <iostream>

using u64 = std::uint64_t;

u64 *test() {
    u64 *a, *p;

    p = (u64 *)&a;
    a = (u64 *)&p;

    {
        for (int i = 0; i < 100; ++i) {
            p = new u64((u64)p);
        }
    }

    while (true) {
        if ((u64)p == 0) {
            break;
        }

        p = (u64 *)*p;
    }

    return p;
}

int main() {
    std::cout << test() << std::endl;
}

And the compiled asm of function test is the following:

test():
        xor     eax, eax
        ret

You can see https://godbolt.org/z/8eTd8WMzG.

In fact, it's expected when the final stmt is return a; although the compiler tells a warning about retuning a local address. And if I make a and p being global variables, everything is ok, see https://godbolt.org/z/n7YWzGvd5.

So, I think that maybe I face some ubs so that its behavior not match my expectation?

Upvotes: 3

Views: 239

Answers (1)

J&#233;r&#244;me Richard
J&#233;r&#244;me Richard

Reputation: 50846

The instructions p = (u64 *)&a; and a = (u64 *)&p; followed by assignments and the dereferencing of the variables break the strict aliasing rule resulting in a undefined behaviour. Indeed, p and a are of type u64* while &a and &p are of type u64**. Moreover, p = (u64 *)*p; is a perfect example of instruction breaking the strict aliasing rule: u64**, u64* and u64 are three distinct different types.

If you want to solve this, you first need to check the size and the alignment of the types match (it should be fine on a mainstream 64-bit architecture). Moreover, you should use a std::bit_cast or a memcpy to perform the conversions (see this related post).

Moreover, note that infinite loops without side-effects are undefined behaviour too. Since p cannot be null in your case. A compiler detecting that your loop is infinite and does not have any side effect can just remove it (or can generate a wrong code too).

Upvotes: 3

Related Questions