Reputation: 24719
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.
Upvotes: 11
Views: 1443
Reputation: 2923
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]
Upvotes: 11
Reputation: 53037
I like to use the trick of using the same name for the members as the constructor parameters.
template <class T>
request_handler(T& request, Log& error_log)
: request(request), error_log(error_log)
{
/*... some code ... */
}
This will always prevent the error. You have to be careful though as in the function body request
refers to argument, not the member. This of course doesn't matter for simple types such as references, but I don't recommend it for classes.
Upvotes: 3