OpenGL Segmentation Fault [Solved]


CubbyFlow에서 Visualization 파트를 맡게 되어서 CubbyRender branch에서 opengl 개발중에 있는데, OpenGL 개발은 혼자서 실험적으로 해본적 많지만, 이렇게 큰 프로젝트에서 메인으로 맡게된 것은 처음이었다.

OpenGL 뿐만 아니고, Framework를 잘 설계해서 DirectX, Vulkan 등의 연동도 고려하는 중이라서 architecture를 크게크게 그리고 있는데 이슈가 발생했다.

Application을 생성하고 Shader, Vertex Buffer 등의 생성 그리고 메인 루프까지는 아무 문제없이 동작한다. 그런데 프로그램이 종료될 때 Segmentation Fault가 발생한다.

Visual Studio에서 벗어나 Ubuntu server에서 gdb로 디버깅 하는 경험은 적은지라 조금 해멨는데, segmentation fault가 발생했을 때 어느 부분에서 발생한 것인지를 알아야하는데 이 방법을 몰랐다.

일단은, backtrace를 이용해서 segmentation fault가 일어났을 때의 frame stack을 살펴보았다.

Thread 1 "GL3Examples" received signal SIGSEGV, Segmentation fault.
0x00007ffff5613bc0 in ?? ()
(gdb) bt
#0  0x00007ffff5613bc0 in ?? ()
#1  0x0000555555688737 in CubbyFlow::CubbyRender::GL3VertexArrayObject::onRelease (this=0x555555c2eee0)
    at ../Experimental/Sources/CubbyRender/GL3/Buffer/GL3VertexArrayObject.cpp:57
#2  0x000055555564a2bf in CubbyFlow::CubbyRender::InputLayout::release (this=0x555555c2eee0)
    at ../Experimental/Sources/CubbyRender/Framework/Buffers/InputLayout.cpp:66
#3  0x0000555555688562 in CubbyFlow::CubbyRender::GL3VertexArrayObject::~GL3VertexArrayObject (this=0x555555c2eee0, __in_chrg=)
    at ../Experimental/Sources/CubbyRender/GL3/Buffer/GL3VertexArrayObject.cpp:33
#4  0x00005555556871eb in __gnu_cxx::new_allocator::destroy (
    this=0x555555c2eee0, __p=0x555555c2eee0) at /usr/include/c++/7/ext/new_allocator.h:140
#5  0x00005555556870b9 in std::allocator_traits<std::allocator >::destroy (__a=..., __p=0x555555c2eee0) at /usr/include/c++/7/bits/alloc_traits.h:487
#6  0x0000555555686d6e in std::_Sp_counted_ptr_inplace<CubbyFlow::CubbyRender::GL3VertexArrayObject, std::allocator, (__gnu_cxx::_Lock_policy)2>::_M_dispose (this=0x555555c2eed0) at /usr/include/c++/7/bits/shared_ptr_base.h:535
#7  0x00005555556045a0 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x555555c2eed0)
    at /usr/include/c++/7/bits/shared_ptr_base.h:154
#8  0x00005555555f8a11 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=0x7fffffffd2c8, __in_chrg=)
---Type  to continue, or q  to quit---
    at /usr/include/c++/7/bits/shared_ptr_base.h:684
#9  0x00005555555f47f4 in std::__shared_ptr<CubbyFlow::CubbyRender::InputLayout, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (this=0x7fffffffd2c0, 
    __in_chrg=) at /usr/include/c++/7/bits/shared_ptr_base.h:1123
#10 0x00005555555f4834 in std::shared_ptr::~shared_ptr (this=0x7fffffffd2c0, __in_chrg=)
    at /usr/include/c++/7/bits/shared_ptr.h:93
#11 0x00005555555e2dc7 in RunExample1 (application=std::shared_ptr (use count 2, weak count 0) = {...}, resX=800, 
    resY=600, numberOfFrames=60) at ../Experimental/Examples/GL3Examples/main.cpp:99
#12 0x00005555555e557a in main (argc=1, argv=0x7fffffffe328) at ../Experimental/Examples/GL3Examples/main.cpp:200

frame stack을 살펴보니 main 함수에서 RunExample1을 수행하고 끝날 때, shared_ptr<InputLayout>ref count가 0이 되면서 InputLayoutdestructor가 호출되고, destructorvirtual로 선언되었기에 GL3VertexArrayObjectdestructor도 호출되고 결국은 GL3VertexArrayObjectonRelease method까지 이어진다.

GL3VertexArrayObjectonRelease method의 코드는 다음과 같다.

void GL3VertexArrayObject::onRelease() 
{
    if (static_cast<int>(_vertexArrayID))
        glDeleteVertexArrays(1, &_vertexArrayID);
}

정말 단순한 코드다 _vertexArrayID가 0이 아니라면 glDeleteVertexArrays를 호출하여 _vertexArrayID에 할당된 opengl object를 해제한다. 결국은 segmentation faultglDeleteVertexArrays에서 발생한 것인데… 뭐가 문제일까?

문제는 RunExample1 함수에서의 OpenGL Object들의 destroy 순서에 있었다. Application 객체가 terminate method를 호출하면 glfw를 이용하여 glfwWindow를 삭제하고 opengl context를 파괴한다. 문제는 다른 opengl object들이 해제 되기도 전에 context가 없어져버리니, glDelete call들에서 프로그램이 터져버리는 것이다.




© 2020.11. by snowapril

Powered by snowapril