I am using glfw as part of my application. I recently ran Valgrind’s Memcheck which reports an invalid read.
Invalid read of size 4
at 0x4C3DEF4: pthread_mutex_lock@@GLIBC_2.2.5 (pthread_mutex_lock.c:80)
by 0x51DB32A: ??? (in /usr/lib/x86_64-linux-gnu/libwayland-client.so.0.22.0)
by 0x51DB5DB: wl_display_dispatch_queue_pending (in /usr/lib/x86_64-linux-gnu/libwayland-client.so.0.22.0)
by 0x171ABE: handleEvents (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x171978: _glfwPollEventsWayland (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x156B05: glfwPollEvents (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x11EF64: Hamster::Window::Update(bool) (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x119657: Hamster::Application::Run() (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x116EA0: main (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
Address 0x4de7bb8 is 296 bytes inside a block of size 376 free'd
at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x16BFA4: _glfwTerminateWayland (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x14B6E6: terminate (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x14B7AD: glfwTerminate (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x11EEB5: Hamster::Window::~Window() (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x11AE8A: std::default_delete<Hamster::Window>::operator()(Hamster::Window*) const (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x11ADAF: std::__uniq_ptr_impl<Hamster::Window, std::default_delete<Hamster::Window> >::reset(Hamster::Window*) (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x11A7BC: std::unique_ptr<Hamster::Window, std::default_delete<Hamster::Window> >::reset(Hamster::Window*) (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x1198E4: Hamster::Application::Close(Hamster::WindowCloseEvent&) (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x119D3F: Hamster::Application::Application()::$_0::operator()(Hamster::Event&) const (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x119D01: void std::__invoke_impl<void, Hamster::Application::Application()::$_0&, Hamster::Event&>(std::__invoke_other, Hamster::Application::Application()::$_0&, Hamster::Event&) (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x119C91: std::enable_if<is_invocable_r_v<void, Hamster::Application::Application()::$_0&, Hamster::Event&>, void>::type std::__invoke_r<void, Hamster::Application::Application()::$_0&, Hamster::Event&>(Hamster::Application::Application()::$_0&, Hamster::Event&) (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
Block was alloc'd at
at 0x484DA83: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x51DE0F3: wl_display_connect_to_fd (in /usr/lib/x86_64-linux-gnu/libwayland-client.so.0.22.0)
by 0x51DE38D: wl_display_connect (in /usr/lib/x86_64-linux-gnu/libwayland-client.so.0.22.0)
by 0x16A2E0: _glfwConnectWayland (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x152135: _glfwSelectPlatform (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x14B3ED: glfwInit (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x11ECF9: Hamster::Window::Window(Hamster::WindowProps const&) (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x11A478: std::_MakeUniq<Hamster::Window>::__single_object std::make_unique<Hamster::Window, Hamster::WindowProps&>(Hamster::WindowProps&) (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x118E48: Hamster::Application::Application() (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
by 0x116CE7: main (in /home/jaden/Documents/dev/Hamster/Hamster-App/Hamster-App)
A window is created when an application is created, the window is stored as a unique pointer as part of the application class. When glfw callsback for a window close, I handle it with Application::Close
, which resets the unique pointer, destroying the window object. The main run loop is then shutdown.
Application.cpp
Application::Application() {
WindowProps props;
m_Window = std::make_unique<Window>(props);
Renderer::Init(props.width, props.height);
m_Dispatcher = std::make_unique<EventDispatcher>();
m_Window->SetWindowEventDispatcher(m_Dispatcher.get());
m_Dispatcher->Subscribe(
WindowClose,
FORWARD_CALLBACK_FUNCTION(Application::Close, WindowCloseEvent));
glfwSetWindowCloseCallback(
m_Window->GetGLFWWindowPointer(), [](GLFWwindow *windowGLFW) {
EventDispatcher *dispatcher =
(EventDispatcher *)glfwGetWindowUserPointer(windowGLFW);
WindowCloseEvent e;
dispatcher->Post<WindowCloseEvent>(e);
});
}
Application::~Application() {
std::cout << "Application destroyed" << std::endl;
}
void Application::Run() {
while (m_running) {
m_Window->Update(m_running);
}
}
void Application::Close(WindowCloseEvent &e) {
m_Window.reset();
m_running = false;
std::cout << "Application closed" << std::endl;
}
window.cpp
Window::Window(const WindowProps &props) {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow *window = glfwCreateWindow(props.width, props.height,
props.title.c_str(), NULL, NULL);
if (window == NULL) {
std::cout << "Window creation failed" << std::endl;
} else {
s_NumWindows += 1;
}
m_Window = window;
glfwMakeContextCurrent(window);
}
Window::~Window() {
glfwDestroyWindow(m_Window);
glfwTerminate();
}
void Window::Update(bool running) {
glfwSwapBuffers(m_Window);
glfwPollEvents();
}
The program compiles and executes with no errors. I suspect the error is in that during the glfwPollEvents()
call, the window is destroyed, during the Window::Update
call in Application.cpp
, the window unique pointer is valid before glfwPollEvents()
but not after (before the update scope exits). Given that this is a single threaded application, I’m stumped as to how this is happening.
JadenJin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.