Search code examples
c++optimizationmemory-leaksmachine-code

C++ O2 Memory leak when using const reference to literal in class


When I was implementing a program, I found that my program behaves differently when switching from -g to -O2 in either g++ or clang++.

The simplified code is:

#include <cstdint>
#include <iostream>
class A {
 public:
  explicit A(const int64_t &zero_);
  const int64_t& zero;
};
A::A(const int64_t &zero_):
  zero(zero_) {
  std::cout << "zero=" << zero << std::endl;
}
int main() {
  A st(0);
  size_t p;
  std::cin >> p;
  std::cout << "zero=" << st.zero << std::endl;
}

Assume the standard input is 1, and the excepted output (in the last line) is zero=0 since the variable zero is a const reference.

When compiled with g++ -g -o b.o b.cc, the program behaves normally.

However, when compiled with g++ -O2 -o b.o b.cc, the output is zero=1

In fact, it outputs the value of p.

Is this a bug or expected behavior?

Tested on Debian10 amd64


Solution

  • A::zero is a dangling reference and hence UB.

    When you construct st, a temporary is created to pass the parameter. This temporary goes out of scope at the end of the statement but st.zero is still referring to it. Therefore, mysterious things happen when you try to use it.

    The difference between -g and -O2 is coincidental. With UB, different things can happen depending on the exact circumstances.