GLFWTerminate是否存在内存泄漏?请求协助排查
GLFW + Valgrind 内存泄漏排查
问题描述
我最近在项目里使用GLFW,打算通过Valgrind做内存泄漏检查。结果运行后报告显示程序退出时存在两处内存泄漏!我确认自己没有遗漏任何清理步骤,所以来求助,帮忙找出代码中可能导致泄漏的问题。
Valgrind 输出结果
==113534== HEAP SUMMARY: ==113534== in use at exit: 183,908 bytes in 2,272 blocks ==113534== total heap usage: 30,407 allocs, 28,135 frees, 14,042,095 bytes allocated ==113534== ==113534== 184 (40 direct, 144 indirect) bytes in 1 blocks are definitely lost in loss record 2,203 of 2,225 ==113534== at 0x484BC13: calloc (vg_replace_malloc.c:1675) ==113534== by 0x5F4B44F: ??? ==113534== by 0x5F407A0: ??? ==113534== by 0x138754: _glfwInitEGL (in /mnt/Storage/Development/Current/leto/build/Leto/Leto) ==113534== by 0x133B26: _glfwCreateWindowWayland (in /mnt/Storage/Development/Current/leto/build/Leto/Leto) ==113534== by 0x1239E2: glfwCreateWindow (in /mnt/Storage/Development/Current/leto/build/Leto/Leto) ==113534== by 0x1149B1: CreateWindow (Window.c:28) ==113534== by 0x114131: main (Main.c:5) ==113534== ==113534== 2,872 (2,688 direct, 184 indirect) bytes in 1 blocks are definitely lost in loss record 2,221 of 2,225 ==113534== at 0x484BC13: calloc (vg_replace_malloc.c:1675) ==113534== by 0x5F4B9AF: ??? ==113534== by 0x5F4C0CF: ??? ==113534== by 0x5E738F4: ??? ==113534== by 0x138671: _glfwInitEGL (in /mnt/Storage/Development/Current/leto/build/Leto/Leto) ==113534== by 0x133B26: _glfwCreateWindowWayland (in /mnt/Storage/Development/Current/leto/build/Leto/Leto) ==113534== by 0x1239E2: glfwCreateWindow (in /mnt/Storage/Development/Current/leto/build/Leto/Leto) ==113534== by 0x1149B1: CreateWindow (Window.c:28) ==113534== by 0x114131: main (Main.c:5) ==113534== ==113534== LEAK SUMMARY: ==113534== definitely lost: 2,728 bytes in 2 blocks ==113534== indirectly lost: 328 bytes in 3 blocks ==113534== possibly lost: 0 bytes in 0 blocks ==113534== still reachable: 180,852 bytes in 2,267 blocks ==113534== suppressed: 0 bytes in 0 blocks
项目源码
Window.h
// Window.h #include <Diagnostic/Platform.h> #include <glad.h> #include <glfw3.h> #include <stdint.h> typedef struct { char title[128]; GLFWwindow* _w; } window_t; const window_t* CreateWindow(const char* title); void DestroyWindow(void);
Window.c
// Window.c #include "Window.h" #include "Output/Reporter.h" #include <stdbool.h> #include <string.h> static window_t application_window = {"", NULL}; const window_t* CreateWindow(const char* title) { if (application_window._w != NULL) { ReportWarning(double_window_creation); return &application_window; } bool init_success = glfwInit(); if (!init_success) ReportError(glfw_init_failed); // OpenGL Core v4.6 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); strncat(application_window.title, title, 64); strncat(application_window.title, " | v" __LETO__VERSION__STRING__, 64); application_window._w = glfwCreateWindow(640, 480, application_window.title, NULL, NULL); if (application_window._w == NULL) ReportError(glfw_window_create_failed); glfwMakeContextCurrent(application_window._w); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) ReportError(opengl_init_failed); while (!glfwWindowShouldClose(application_window._w)) { glClear(GL_COLOR_BUFFER_BIT); glfwSwapBuffers(application_window._w); glfwPollEvents(); } return &application_window; } void DestroyWindow(void) { if (application_window._w == NULL) { ReportWarning(preemptive_window_free); return; } glfwMakeContextCurrent(NULL); glfwDestroyWindow(application_window._w); glfwTerminate(); }
Main.c
// Main.c #include <Windowing/Window.h> int main(int argc, char** argv) { CreateWindow("Leto"); DestroyWindow(); }
排查结论与解决方案
从Valgrind的栈回溯可以明确,泄漏的内存来自GLFW内部的_glfwInitEGL函数,属于Wayland平台下EGL初始化阶段的分配。你的代码已经严格遵循GLFW的清理流程:调用glfwDestroyWindow销毁窗口,再调用glfwTerminate终止GLFW环境,没有遗漏任何必要步骤,所以这不是你的代码导致的泄漏,而是GLFW库自身的平台相关bug。
解决建议
- 升级GLFW版本:这类平台特定的内存泄漏问题,GLFW官方在后续版本中大概率会修复,建议升级到最新的稳定版本后再测试。
- 忽略该泄漏:如果暂时无法升级,这部分泄漏属于GLFW内部资源,不会影响程序的正常运行和稳定性,可以安全忽略。
- 切换平台验证:尝试在X11环境下运行程序,若泄漏消失,即可确认是Wayland后端的问题。
额外代码细节提示
你的strncat使用存在潜在风险:application_window.title初始为空字符串,首次拼接没问题,但如果重复调用CreateWindow(虽然你加了非空判断),可能会导致字符串溢出,建议改为strncpy初始化后再拼接,不过这和当前的内存泄漏问题无关。
内容的提问来源于stack exchange,提问作者Zenais
相关产品推荐
相关产品推荐

