使用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也无泄漏提示。
疑问
- 这种极简SDL2程序出现内存泄漏是否正常?
- 若正常,如何区分我的库的泄漏是来自自身代码还是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
相关产品推荐
相关产品推荐

