如何在基于 Qt 的应用程序中正确使用 valgrind

Posted

技术标签:

【中文标题】如何在基于 Qt 的应用程序中正确使用 valgrind【英文标题】:How to properly use valgrind in Qt based app 【发布时间】:2021-01-08 09:48:44 【问题描述】:

我正在尝试检查我的 Qt 应用程序是否存在内存泄漏。我尝试在 QTCreator 中可用的示例项目上使用 valgrind。它是使用 QMainWindow 类的 GUI 应用程序。 Valgrind 发现了很多漏洞:

==6426== Memcheck, a memory error detector
==6426== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6426== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==6426== Command: ./project
==6426== 
--6426-- WARNING: unhandled amd64-linux syscall: 315
--6426-- You may be able to write your own handler.
--6426-- Read the file README_MISSING_SYSCALL_OR_IOCTL.
--6426-- Nevertheless we consider this a bug.  Please report
--6426-- it at http://valgrind.org/support/bug_reports.html.
==6426== Invalid read of size 8
==6426==    at 0x40209E8: strncmp (strcmp.S:175)
==6426==    by 0x40066ED: is_dst (dl-load.c:209)
==6426==    by 0x4009A2E: _dl_dst_count (dl-load.c:246)
==6426==    by 0x4009A2E: expand_dynamic_string_token (dl-load.c:388)
==6426==    by 0x4009BE1: fillin_rpath (dl-load.c:460)
==6426==    by 0x4009F43: decompose_rpath.isra.0 (dl-load.c:631)
==6426==    by 0x400ACCE: cache_rpath (dl-load.c:673)
==6426==    by 0x400ACCE: cache_rpath (dl-load.c:654)
==6426==    by 0x400ACCE: _dl_map_object (dl-load.c:2074)
==6426==    by 0x400F504: openaux (dl-deps.c:64)
==6426==    by 0x60198B7: _dl_catch_exception (dl-error-skeleton.c:208)
==6426==    by 0x400F952: _dl_map_object_deps (dl-deps.c:248)
==6426==    by 0x4015D9F: dl_open_worker (dl-open.c:571)
==6426==    by 0x60198B7: _dl_catch_exception (dl-error-skeleton.c:208)
==6426==    by 0x40155F9: _dl_open (dl-open.c:837)
==6426==  Address 0x96046d9 is 9 bytes inside a block of size 15 alloc'd
==6426==    at 0x4A37ECB: malloc (vg_replace_malloc.c:307)
==6426==    by 0x401F53E: strdup (strdup.c:42)
==6426==    by 0x4009ED4: decompose_rpath.isra.0 (dl-load.c:606)
==6426==    by 0x400ACCE: cache_rpath (dl-load.c:673)
==6426==    by 0x400ACCE: cache_rpath (dl-load.c:654)
==6426==    by 0x400ACCE: _dl_map_object (dl-load.c:2074)
==6426==    by 0x400F504: openaux (dl-deps.c:64)
==6426==    by 0x60198B7: _dl_catch_exception (dl-error-skeleton.c:208)
==6426==    by 0x400F952: _dl_map_object_deps (dl-deps.c:248)
==6426==    by 0x4015D9F: dl_open_worker (dl-open.c:571)
==6426==    by 0x60198B7: _dl_catch_exception (dl-error-skeleton.c:208)
==6426==    by 0x40155F9: _dl_open (dl-open.c:837)
==6426==    by 0x8E2834B: dlopen_doit (dlopen.c:66)
==6426==    by 0x60198B7: _dl_catch_exception (dl-error-skeleton.c:208)
==6426== 
==6426== Invalid read of size 8
==6426==    at 0x40209E8: strncmp (strcmp.S:175)
==6426==    by 0x40066ED: is_dst (dl-load.c:209)
==6426==    by 0x40098AE: _dl_dst_substitute (dl-load.c:288)
==6426==    by 0x4009BE1: fillin_rpath (dl-load.c:460)
==6426==    by 0x4009F43: decompose_rpath.isra.0 (dl-load.c:631)
==6426==    by 0x400ACCE: cache_rpath (dl-load.c:673)
==6426==    by 0x400ACCE: cache_rpath (dl-load.c:654)
==6426==    by 0x400ACCE: _dl_map_object (dl-load.c:2074)
==6426==    by 0x400F504: openaux (dl-deps.c:64)
==6426==    by 0x60198B7: _dl_catch_exception (dl-error-skeleton.c:208)
==6426==    by 0x400F952: _dl_map_object_deps (dl-deps.c:248)
==6426==    by 0x4015D9F: dl_open_worker (dl-open.c:571)
==6426==    by 0x60198B7: _dl_catch_exception (dl-error-skeleton.c:208)
==6426==    by 0x40155F9: _dl_open (dl-open.c:837)
==6426==  Address 0x96046d9 is 9 bytes inside a block of size 15 alloc'd
==6426==    at 0x4A37ECB: malloc (vg_replace_malloc.c:307)
==6426==    by 0x401F53E: strdup (strdup.c:42)
==6426==    by 0x4009ED4: decompose_rpath.isra.0 (dl-load.c:606)
==6426==    by 0x400ACCE: cache_rpath (dl-load.c:673)
==6426==    by 0x400ACCE: cache_rpath (dl-load.c:654)
==6426==    by 0x400ACCE: _dl_map_object (dl-load.c:2074)
==6426==    by 0x400F504: openaux (dl-deps.c:64)
==6426==    by 0x60198B7: _dl_catch_exception (dl-error-skeleton.c:208)
==6426==    by 0x400F952: _dl_map_object_deps (dl-deps.c:248)
==6426==    by 0x4015D9F: dl_open_worker (dl-open.c:571)
==6426==    by 0x60198B7: _dl_catch_exception (dl-error-skeleton.c:208)
==6426==    by 0x40155F9: _dl_open (dl-open.c:837)
==6426==    by 0x8E2834B: dlopen_doit (dlopen.c:66)
==6426==    by 0x60198B7: _dl_catch_exception (dl-error-skeleton.c:208)
==6426== 
==6426== 
==6426== HEAP SUMMARY:
==6426==     in use at exit: 2,479,965 bytes in 27,792 blocks
==6426==   total heap usage: 332,697 allocs, 304,905 frees, 27,650,747 bytes allocated
==6426== 
==6426== LEAK SUMMARY:
==6426==    definitely lost: 6,760 bytes in 27 blocks
==6426==    indirectly lost: 4,492 bytes in 134 blocks
==6426==      possibly lost: 3,840 bytes in 33 blocks
==6426==    still reachable: 2,382,241 bytes in 26,924 blocks
==6426==                       of which reachable via heuristic:
==6426==                         length64           : 4,960 bytes in 82 blocks
==6426==                         newarray           : 2,096 bytes in 51 blocks
==6426==         suppressed: 0 bytes in 0 blocks
==6426== Rerun with --leak-check=full to see details of leaked memory
==6426== 
==6426== For lists of detected and suppressed errors, rerun with: -s
==6426== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

我可能缺少在 valgrind 中设置的一些选项,因为我使用了“纯”valgrind。我使用的命令:valgrind ./project。我在 Ubuntu 20.04 上完成的所有测试。 当我使用 QtCreator 中内置的 valgrind 时,我得到“发现 37 个问题”,但它们没有显示在 memcheck 视图中。

【问题讨论】:

Suppression files for Qt memory leaks with Valgrind 有帮助吗? 这是解决问题的方法。 太棒了!如果您通过为内置 Qt 泄漏创建抑制文件解决了问题,您可以将其发布为您自己问题的答案。 【参考方案1】:

您可能需要从源代码构建 Valgrind 以获得 sched_getattr 系统调用,它是在 3.16.1 发布后添加的。

从 git blame 中提取。

6323fd5b coregrind/m_syswrap/syswrap-amd64-linux.c   (Mark Wielaard         2020-07-27 16:36:17 +0200 850)    LINXY(__NR_sched_getattr,     sys_sched_getattr),    // 315

【讨论】:

有没有其他方法可以检查是否有内存泄漏? Heaptrack 确实报告了泄漏,但我从未将它用于此目的。如果您的工具链支持,Leak sanitizer 也是一个不错的选择。

以上是关于如何在基于 Qt 的应用程序中正确使用 valgrind的主要内容,如果未能解决你的问题,请参考以下文章

如何从主窗体完全/正确退出 Qt 程序?

在 Qt 中正确使用 C++11 基于范围的 for 循环

如何使用计时器正确更新 QTableView?

如何在 QT 中正确显示 std::vector?

如何测试 Qt4 应用程序的正确 QNetworkProxy 工作?

如何在基于 Qt 的应用程序中支持多种语言