skip to Main Content

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


  1. Chosen as BEST ANSWER

    Thanks all ! At the end of the day, I solved my issue by just removing the const & from my template AutoDestruct.

    template <class TYPE,class FUNC> struct AutoDestruct
        {
        TYPE         var ;
        FUNC         func ;
        AutoDestruct ( TYPE v , FUNC f ) : var(v),func(f) {}
       ~AutoDestruct ()                          { func(var) ;}
        };
    

    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.


  2. 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:

    #include <iostream>
    using namespace std;
    
    template <class TYPE,class FUNC> struct AutoDestruct {
        TYPE& var ;
        FUNC func ;
        AutoDestruct(TYPE& v, FUNC f ) : var(v),func(f) {}
        ~AutoDestruct () { func(var) ;}
    };
    
    struct Dictionary {
        Dictionary & wipe  () { cout << "Dictionary.wipe()n" ; return *this ;}
    };
    
    static void wipe_dict ( Dictionary & dict ) { dict.wipe() ;}
    typedef AutoDestruct<Dictionary,void(*)(Dictionary&)> AutoWipe ;
        
    int main () {
        Dictionary headers ;
        AutoWipe auto_wipe( headers,wipe_dict) ;
    }
    

    auto_wipe stores a reference to headers, and when its destructor is called it calls headers.wipe();. Then headers destructor is called and all is fine.

    Though in your code, here:

    AutoWipe   auto_wipe( &headers,wipe_dict ) ;
    

    Your auto_wipe stores a reference to the temporary pointer returned by &headers. When auto_wipe‘s destructor is called, the object headers 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search