I saw many other questions about the very same warning, but my code seems different.
And, over all, I get this only with -Os option.
#include <iostream>
using namespace std ;
template <class TYPE,class FUNC> struct AutoDestruct
{
const TYPE & var ;
FUNC func ;
AutoDestruct ( const TYPE & v , FUNC f ) : var(v),func(f) {}
~AutoDestruct () { func(var) ;}
};
class Dictionary
{
public:
Dictionary & wipe () { cout << "Dictionary.wipe()n" ; return *this ;}
};
static void wipe_dict ( Dictionary * dict ) { dict->wipe() ;}
typedef AutoDestruct<Dictionary*,void(*)(Dictionary*)> AutoWipe ;
int main ()
{
cout << "enter main function " << __DATE__ << " " << __TIME__ << endl ;
Dictionary headers ;
AutoWipe auto_wipe( &headers,wipe_dict ) ;
cout << "exit main functionn" ;
}
The command line is :
g++ -std=c++11 -Os -Wall -Wextra test.cpp && ./a.out
N.B.: If I remove the -Os option, I get no warning.
The output is :
test.cpp: In function ‘int main()’:
test.cpp:9:48: warning: ‘<anonymous>’ may be used uninitialized [-Wmaybe-uninitialized]
9 | ~AutoDestruct () { func(var) ;}
| ^~~~
test.cpp:25:46: note: ‘<anonymous>’ was declared here
25 | AutoWipe auto_wipe( &headers,wipe_dict ) ;
| ^
enter main function May 13 2024 20:14:01
exit main function
Dictionary.wipe()
and the compiler is :
g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
This is a very simple extract of my real code, just to expose the warning.
But notice that in my real code, I get the warning AND a seg fault when executing the auto_wipe !
Any idea of the warning + seg fault cause ?
Thanks in advance !
2
Answers
Thanks all ! At the end of the day, I solved my issue by just removing the const & from my template AutoDestruct.
So var stores a pointer and no more a reference.
Thanks to the reverse order of the call of the destructors, I'm sure that wipe is called before the object is destructed.
I think it is worthwhile to take a small detour because I suppose I wasn’t the only one who initially misread your code. The code I thought I was reading is this:
auto_wipe
stores a reference toheaders
, and when its destructor is called it callsheaders.wipe();
. Thenheaders
destructor is called and all is fine.Though in your code, here:
Your
auto_wipe
stores a reference to the temporary pointer returned by&headers
. Whenauto_wipe
‘s destructor is called, the objectheaders
is of course still stored at the same memory address. Nevertheless, the temporary pointer resulting from&headers
is long gone and the member is a dangling reference. You can either copy the pointer, as suggested in comments, or store a reference to the actual object, as above.TL;DR: The compiler is right to warn. You store a dangling reference. Using an address sanitizer will highlight the issue.