1

This is a GCC specific issue. I'm encountering a werid issue in a .so library. The demo code of this .so library could be:

__attribute__((init_priority(101))) std::unique_ptr<object_t> global_object;

__attribute__((constructor)) void entry_constructor() {
    global_object = make_unique<object_t>();
}

__attribute__((destructor)) void entry_destructor() {
    global_object.reset(nullptr);
}

I know the global global_object would be released automatically even without entry_destructor. But I just want to give you an example. For debug building, the entry_destructor runs well. But for release building, it crashed.

I set break points and debugged this issue. In debug build, the entry_destructor is executed firstly, then runs std::unique_ptr::destructor. But in release build, the std::unique_ptr::destructor is run before entry_destructor.

Firstly hit here:

#3  std::unique_ptr<...> >::~unique_ptr (this=<optimized out>, __in_chrg=<optimized out>) at /usr/include/c++/7/bits/unique_ptr.h:263
#4  0x00007ffff5b8c0f1 in __run_exit_handlers (status=0, listp=0x7ffff5f34718 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at exit.c:108
#5  0x00007ffff5b8c1ea in __GI_exit (status=<optimized out>) at exit.c:139
#6  0x00007ffff5b6ab9e in __libc_start_main (main=0x555555672c51 <main(int, char**)>, argc=1, argv=0x7fffffffe2b8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe2a8) at ../csu/libc-start.c:344
#7  0x000055555566eb0a in _start ()

Then hit here:

#3  std::unique_ptr<...>::reset (__p=0x555555893ae0, this=0x55555585bc70 <...>) at /usr/include/c++/7/bits/unique_ptr.h:371
#5  0x000055555567b021 in entry_destructor () at ...
#6  0x00007ffff7de5bc3 in _dl_fini () at dl-fini.c:138
#7  0x00007ffff5b8c0f1 in __run_exit_handlers (status=0, listp=0x7ffff5f34718 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at exit.c:108
#8  0x00007ffff5b8c1ea in __GI_exit (status=<optimized out>) at exit.c:139
#9  0x00007ffff5b6ab9e in __libc_start_main (main=0x555555672c51 <main(int, char**)>, argc=1, argv=0x7fffffffe2b8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe2a8) at ../csu/libc-start.c:344
#10 0x000055555566eb0a in _start ()

I marked global_object as __attribute__((init_priority(101))) because only by that it can be initialized before entry_construtor, otherwise entry_contructor would crash when accessing global_object.

I also tried to mark global_object as static, but it didn't help either.

I hope all global variables should be destructed after entry_destructor, whether it's debug build or release build. All the documents and discussions I can find are about the construt and destruct order or global variables, but not the order between global variable destruct and __attribute__((destructor)). Is there any GCC rule for that? Or is it an undefined behavior?

xnervwang
  • 75
  • 5

0 Answers0