cginternals / globjects

C++ library strictly wrapping OpenGL objects.
https://globjects.org
MIT License
538 stars 59 forks source link

Program segfault in IDTreat::id() #364

Open X-Ryl669 opened 6 years ago

X-Ryl669 commented 6 years ago

I've finally updated my code to the current master. I've removed all ref_ptr in my code, and instead used std::unique_ptr and some custom ScopedPointer elsewhere or plain instance. However, when the program is closing, it's crashing with this callstack:

Thread 1 "Stitcher" received signal SIGSEGV, Stopped (user).
0x00007fb982342600 in globjects::IDTrait::id() const () from /usr/local/lib/libglobjects.so.2
(gdb) bt
#0  0x00007fb982342600 in globjects::IDTrait::id() const () from /usr/local/lib/libglobjects.so.2
#1  0x00007fb98232bfa2 in globjects::Object::id() const () from /usr/local/lib/libglobjects.so.2
#2  0x00007fb98232e058 in globjects::Program::detach(globjects::Shader*) () from /usr/local/lib/libglobjects.so.2
#3  0x00007fb982343fd6 in globjects::Shader::~Shader() () from /usr/local/lib/libglobjects.so.2
#4  0x000055d0186ce528 in GL::ScreenPlane::~ScreenPlane (this=0x55d01c085a30, __in_chrg=<optimized out>) at ../src/../include/GLPlane.hpp:29
[...] // My stuff here
#9  Stitcher::Application::~Application (this=0x55d018c61dc0 <Stitcher::Application::getInstance()::app>, __in_chrg=<optimized out>) at ../src/../include/Application.hpp:38
#10 0x00007fb97eecd448 in __run_exit_handlers () from /usr/lib/libc.so.6
#11 0x00007fb97eecd49a in exit () from /usr/lib/libc.so.6
#12 0x00007fb97eeb6f51 in __libc_start_main () from /usr/lib/libc.so.6
#13 0x000055d0186adf0a in _start ()

Typically, I'm using GLFW for getting the GL context, and it's destroyed when the exit handler are runnings (please notice that the lifetime of the Application singleton instance is longer than main, since it's a static object, so it's being destructed when the exit handlers are running) if it's of any help.

Further debugging gives:

#1  0x00007ffff7a75fa2 in globjects::Object::id (this=0x555558841db0) at ../source/globjects/source/Object.cpp:49
49          return m_resource->id();
(gdb) p *this
$1 = {_vptr.Object = 0x7ffff7dcb838 <vtable for globjects::Object+16>, m_resource = std::unique_ptr<globjects::IDResource> containing 0x0, m_objectLabelState = 0x0}
(gdb) up
#2  0x00007ffff7a78058 in globjects::Program::detach (this=0x555558841db0, shader=0x555558841cc8) at ../source/globjects/source/Program.cpp:140
140         glDetachShader(id(), shader->id());
(gdb) p *shader
$2 = {<globjects::Object> = {_vptr.Object = 0x7ffff7dcc2a8 <vtable for globjects::Shader+16>, m_resource = std::unique_ptr<globjects::IDResource> containing 0x55555883abf0, m_objectLabelState = 0x0}, <globjects::ChangeListener> = {_vptr.ChangeListener = 0x7ffff7dcc2e0 <vtable for globjects::Shader+72>, m_subjects = std::set with 1 element = {
      [0] = 0x555558849d60}}, <globjects::Changeable> = {_vptr.Changeable = 0x7ffff7dcc310 <vtable for globjects::Shader+120>, m_listeners = std::set with 0 elements}, <globjects::Instantiator<globjects::Shader>> = {<No data fields>}, m_type = <incomplete type>, m_source = 0x555558849d60, m_includePaths = std::vector of length 0, capacity 0,
  m_programs = std::set with 1 element = {[0] = 0x555558841db0}, m_compiled = true, m_compilationFailed = false, static s_globalReplacements = {_M_t = {
      _M_impl = {<std::allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >> = {<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >> = {<No data fields>}, <No data fields>}, <std::_Rb_tree_key_compare<std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >> = {
          _M_key_compare = {<std::binary_function<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool>> = {<No data fields>}, <No data fields>}}, <std::_Rb_tree_header> = {_M_header = {_M_color = std::_S_red, _M_parent = 0x0,
            _M_left = 0x7ffff7dd70a8 <globjects::Shader::s_globalReplacements[abi:cxx11]+8>, _M_right = 0x7ffff7dd70a8 <globjects::Shader::s_globalReplacements[abi:cxx11]+8>}, _M_node_count = 0}, <No data fields>}}}}

Clearly, the program does not exist anymore but the shader still do. I've created the Shader like this in my code:

    struct ScreenPlane
    {
[...]
        std::unique_ptr<globjects::AbstractStringSource>            vertShaderSrc;
        std::unique_ptr<globjects::AbstractStringSource>            fragShaderSrc;
        globjects::Shader                                           vertShader;
        globjects::Shader                                           fragShader;

        globjects::Program                                          prog;
[...]
         ScreenPlane([...]) : 
        : vertShaderSrc(Shader::sourceFromString(screenPlaneVertex)),
          vertShader(GL_VERTEX_SHADER, vertShaderSrc.get()),
          fragShaderSrc(Shader::sourceFromFile(fragFileName)),
          fragShader(GL_FRAGMENT_SHADER, fragShaderSrc.get()),
      [...]
    {
        prog.attach(&vertShader, &fragShader);

It seems that the program is destructed before the shader, and this breaks the current code that expect the program to outlive the shader.

scheibel commented 6 years ago

This seems to get solved with explicit deinitialization. We experienced similar errors and had to adapt our examples as well (see #358).