So, I just got through with a grueling multi-hour debug session of a large server application. The error eventually came down to a barely noticeable typo in a constructor. Basically, it was something like:
template <class T>
class request_handler
{
public:
request_handler(T& request, Log& error_log)
: m_request(m_request), m_error_log(error_log)
{
/*... some code ... */
}
...
};
See the bug? Well, I didn't. The problem is a small typo in the initializer list: m_request(m_request)
is assigning an uninitialized reference to itself. Obviously, it's supposed to read m_request(request)
.
Now, the member variable m_request
is of type T&
. So - is there some reason the compiler didn't warn me that I was using an uninitialized variable here?
Using GCC 4.6 with the -Wall
flag, if I say:
int x;
x = x;
...it will issue a warning: warning: ‘x’ is used uninitialized in this function [-Wuninitialized]
So, why didn't the compiler warn me when I assigned m_request
to itself: essentially assigning an uninitialized reference to itself? It would have saved me hours of annoyance.
Annoying bug to track down. It turns out, you don't even need templates to silently fail on this one. This'll do the trick:
class C {
int a, b;
public:
C(int t, int z) : a(a), b(z) { };
};
Clang warns on this with -Wuninitialized
.
Good news for gcc folks: according to gnu's bugzilla, gcc 4.7.0 has fixed this.
Update
On gcc 4.7.0, add -Wself-init
to get this warning (verified by sbellef):
tst.cc: In constructor ‘C::C(int, int)’: tst.cc:4:9: warning: ‘C::a’ is initialized with itself [-Wuninitialized]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With