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

使用Valgrind检测SDL2程序出现异常内存泄漏结果的疑问

关于SDL2极简程序的Valgrind内存泄漏疑问

我正在为SDL2编写自用上层封装库,用Valgrind检测内存泄漏时,运行库的程序会输出大量错误。于是写了个极简SDL2程序测试,结果显示存在内存泄漏。

测试代码(main.c)

int main(void){
    SDL_Init(SDL_INIT_VIDEO);

    SDL_Window *window = SDL_CreateWindow("sxdfcgvh", 0, 0, 720, 480, 0);
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);

    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);

    SDL_Rect rect = {1, 1, 100, 100};
    SDL_Event event;
    SDL_PollEvent(&event);
    while (event.type != SDL_KEYDOWN){
        SDL_PollEvent(&event);
        SDL_RenderClear(renderer);
        SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
        SDL_RenderDrawRect(renderer, &rect);
        SDL_RenderPresent(renderer);
        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    }

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

编译运行命令

gcc main.c -lSDL2main -lSDL2 -O3 -o xyz.out && valgrind --leak-check=yes --track-origins=yes ./xyz.out

Valgrind输出

==30540== HEAP SUMMARY:
==30540==     in use at exit: 335,611 bytes in 3,360 blocks
==30540==   total heap usage: 81,476 allocs, 78,116 frees, 23,727,953 bytes allocated
==30540== 
==30540== 6,592 (232 direct, 6,360 indirect) bytes in 1 blocks are definitely lost in loss record 2,407 of 2,413
==30540==    at 0x484D953: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==30540==    by 0x52E7232: ??? (in /usr/lib/x86_64-linux-gnu/libdbus-1.so.3.32.4)
==30540==    by 0x52EF587: ??? (in /usr/lib/x86_64-linux-gnu/libdbus-1.so.3.32.4)
==30540==    by 0x52F189D: ??? (in /usr/lib/x86_64-linux-gnu/libdbus-1.so.3.32.4)
==30540==    by 0x52E1872: ??? (in /usr/lib/x86_64-linux-gnu/libdbus-1.so.3.32.4)
==30540==    by 0x52CD28D: ??? (in /usr/lib/x86_64-linux-gnu/libdbus-1.so.3.32.4)
==30540==    by 0x52CE6F0: ??? (in /usr/lib/x86_64-linux-gnu/libdbus-1.so.3.32.4)
==30540==    by 0x4996B13: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.3000.0)
==30540==    by 0x48A337E: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.3000.0)
==30540==    by 0x1091EC: main (in /home/pierre/Desktop/Hobbes/programs/C/SDLLearn/xyz.out)
==30540== 
==30540== LEAK SUMMARY:
==30540==    definitely lost: 232 bytes in 1 blocks
==30540==    indirectly lost: 6,360 bytes in 35 blocks
==30540==      possibly lost: 0 bytes in 0 blocks
==30540==    still reachable: 329,019 bytes in 3,324 blocks
==30540==         suppressed: 0 bytes in 0 blocks
==30540== Reachable blocks (those to which a pointer was found) are not shown.
==30540== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==30540== 
==30540== For lists of detected and suppressed errors, rerun with: -s
==30540== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

补充信息

  • 添加-g编译参数后,Valgrind显示内存分配来自SDL_Init(),但仅调用SDL_Init()和SDL_Quit()时无泄漏;
  • 移除SDL_RenderDrawRect()和SDL_RenderPresent()后,Valgrind也无泄漏提示。

疑问

  1. 这种极简SDL2程序出现内存泄漏是否正常?
  2. 若正常,如何区分我的库的泄漏是来自自身代码还是SDL2?

解答

1. 这种情况是否正常?

是正常的。从Valgrind输出能看到,泄漏的内存来自libdbus-1.so——这是SDL在Linux平台上与系统服务交互时依赖的库,并非你的代码或SDL核心逻辑的问题。结合你的补充测试:仅初始化/退出SDL、或者不调用渲染相关函数时无泄漏,说明这是渲染模块与系统服务交互时的残留内存,属于第三方库的“无害泄漏”。这类内存会在进程结束时被操作系统回收,不会造成实际运行时的内存问题。

SDL官方也明确提到过,Valgrind会报告一些来自系统依赖库的假阳性泄漏,尤其是在Linux桌面环境下,这些都不是SDL本身的bug。

2. 如何区分自身代码与SDL的泄漏?

可以通过以下几种实用方法:

  • 标记自有内存分配:给你的封装库中所有自定义的内存分配(malloc/calloc/realloc等)套一层包装函数,比如my_malloc、my_free,然后用Valgrind的--trace-malloc=yes参数跟踪这些函数的调用,就能明确区分哪些分配是你的代码产生的。
  • 对比基准测试:写一个和你的库使用逻辑完全一致,但直接调用SDL原生API的基准程序,运行Valgrind后对比结果。如果基准程序的泄漏情况和你的库完全一致,那泄漏就来自SDL;如果你的库多了额外的泄漏项,那就是你的代码问题。
  • 使用Valgrind抑制文件:SDL官方提供了针对Valgrind的抑制文件,可过滤掉SDL及其依赖库的已知假阳性泄漏。运行Valgrind时加上--suppressions=SDL.supp参数,就能只显示你自己代码的泄漏。
  • 编译SDL调试版本:如果需要进一步确认,可以编译带调试信息的SDL版本,这样Valgrind能显示更详细的调用栈,明确哪些分配是SDL内部逻辑触发的,哪些是你的代码导致的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 01:00:10