You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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。

解决建议

  1. 升级GLFW版本:这类平台特定的内存泄漏问题,GLFW官方在后续版本中大概率会修复,建议升级到最新的稳定版本后再测试。
  2. 忽略该泄漏:如果暂时无法升级,这部分泄漏属于GLFW内部资源,不会影响程序的正常运行和稳定性,可以安全忽略。
  3. 切换平台验证:尝试在X11环境下运行程序,若泄漏消失,即可确认是Wayland后端的问题。

额外代码细节提示

你的strncat使用存在潜在风险:application_window.title初始为空字符串,首次拼接没问题,但如果重复调用CreateWindow(虽然你加了非空判断),可能会导致字符串溢出,建议改为strncpy初始化后再拼接,不过这和当前的内存泄漏问题无关。

内容的提问来源于stack exchange,提问作者Zenais

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 07:34:56