【问题标题】:Valgrind reports memory leak on QThread::start()Valgrind 在 QThread::start() 上报告内存泄漏
【发布时间】:2020-06-02 16:03:45
【问题描述】:

问题出在 VMware 上,不知何故 3D 加速会导致内存泄漏和 SIGSEGV,从而导致程序崩溃。

==============================

我对以下代码有疑问:

    gc = new GameController(scene);
    subthread = new QThread(this);
    gc->moveToThread(subthread);
    subthread->start();

这应该是一个常规的子线程初始化,但是valgrind内存分析器说:

416 bytes in 1 blocks are possibly lost in loss record 8,318 of 8,856
  in Widget::Widget(QWidget*) in /home/closer_ex/QtProjects/LifeGameWithTest/LifeGame/widget.cpp:15
  1: calloc in /builddir/build/BUILD/valgrind-3.15.0/coregrind/m_replacemalloc/vg_replace_malloc.c:762
  2: allocate_dtv in /usr/lib64/ld-2.28.so
  3: _dl_allocate_tls in /usr/lib64/ld-2.28.so
  4: pthread_create@@GLIBC_2.2.5 in /usr/lib64/libpthread-2.28.so
  5: QThread::start(QThread::Priority) in /home/closer_ex/Qt5.13.2/5.13.2/gcc_64/lib/libQt5Core.so.5.13.2
  6: Widget::Widget(QWidget*) in /home/closer_ex/QtProjects/LifeGameWithTest/LifeGame/widget.cpp:15
  7: main in /home/closer_ex/QtProjects/LifeGameWithTest/LifeGame/main.cpp:8

直接指向subthread->start()。 scene 不是父级,而是一个 QGraphicsScene 指针传递给在子线程中进行一些计算,我在我的析构函数中在 quit()&wait() subthread 之后手动 delete gc。程序运行顺利,但我无法进行任何内存分析。

如果我检查外部错误,肯定有 2 个泄漏,导致“vg_replace_malloc.c”中的 QApplication a(argc, argv); 和 malloc。

544 bytes in 11 blocks are definitely lost in loss record 8,418 of 8,861
  in _dl_close_worker in /usr/lib64/ld-2.28.so
  1: malloc in /builddir/build/BUILD/valgrind-3.15.0/coregrind/m_replacemalloc/vg_replace_malloc.c:309
  2: _dl_close_worker in /usr/lib64/ld-2.28.so
  3: _dl_close in /usr/lib64/ld-2.28.so
  4: _dl_catch_exception in /usr/lib64/libc-2.28.so
  5: _dl_catch_error in /usr/lib64/libc-2.28.so
  6: _dlerror_run in /usr/lib64/libdl-2.28.so
  7: dlclose in /usr/lib64/libdl-2.28.so
  8: g_module_close in /usr/lib64/libgmodule-2.0.so.0.5600.4
  9: /usr/lib64/libgio-2.0.so.0.5600.4
  10: g_type_module_unuse in /usr/lib64/libgobject-2.0.so.0.5600.4
  11: /usr/lib64/libgio-2.0.so.0.5600.4
  12: g_io_extension_point_get_extensions in /usr/lib64/libgio-2.0.so.0.5600.4
  13: /usr/lib64/libgio-2.0.so.0.5600.4
  14: g_settings_backend_get_default in /usr/lib64/libgio-2.0.so.0.5600.4
  15: /usr/lib64/libgio-2.0.so.0.5600.4
  16: /usr/lib64/libgobject-2.0.so.0.5600.4
  17: g_object_new_valist in /usr/lib64/libgobject-2.0.so.0.5600.4
  18: g_object_new in /usr/lib64/libgobject-2.0.so.0.5600.4
  19: g_settings_new_full in /usr/lib64/libgio-2.0.so.0.5600.4
  20: /usr/lib64/libgdk-3.so.0.2200.30
  21: /usr/lib64/libgdk-3.so.0.2200.30
  22: gdk_display_manager_open_display in /usr/lib64/libgdk-3.so.0.2200.30
  23: gtk_init_check in /usr/lib64/libgtk-3.so.0.2200.30
  24: gtk_init in /usr/lib64/libgtk-3.so.0.2200.30
  25: QGtk3Theme::QGtk3Theme() in /home/closer_ex/Qt5.13.2/5.13.2/gcc_64/plugins/platformthemes/libqgtk3.so

泄漏可能发生在哪里?

【问题讨论】:

  • 我不知道,但我的猜测是GameController 对象并不拥有您提供给moveToThread 的线程对象的所有权,所以您仍然必须拥有delete subthread;。
  • widget.cpp:15 中的代码行是什么?
  • @OznOg 正如我的标题所说,它是subthread->start();
  • 线程退出前是否加入?
  • @FredLarson subthread 已经有了一个父对象,this 指向主窗口对象。

标签: c++ memory-leaks qt5 valgrind qthread


【解决方案1】:

8856 的丢失记录 8318 中可能丢失 1 个块中的 416 字节

消息可能丢失,这意味着 Widget 仍然可以访问,这不是像 int * x=new int; x = NULL; 中那样确定的内存泄漏

您收到该消息是因为当您的程序完成时您没有删除/释放所有分配的动态内存,这并不意味着您的程序有误。

查看肯定丢失块,如果你没有,其实一切都可以。为此,您可以使用选项 --show-leak-kinds=definite 相当于做 --show-reachable=no --show-possibly-lost=no

【讨论】:

  • 听到这话让人松了一口气,但问题是 valgrind 在这里与程序崩溃,我无法进行进一步的内存分析。顺便说一句,这是唯一的消息。
  • @closer_ex 崩溃了?在生成包含内存泄漏的最终报告时,我从未见过它发生崩溃。你能用--show-leak-kinds=definite选项重做吗?
  • 在外部错误中发现了 2 个明确的泄漏,一个在 main 中导致 QApplication a(argc, argv);,另一个在来自“vg_replace_malloc.c”的 malloc 中。此外,还有更多可能的外部错误泄漏无处可见
  • @closer_ex 我不是让你看vg_replace_malloc.c,而是看报告中valgrind产生的堆栈
  • @closer_ex 你的堆栈很奇怪,你有一个异常,所以可能在执行时崩溃(独立于 valgrind)?
【解决方案2】:

您在 Qt 应用程序中使用 GTK+ 样式。这在崩溃的调用堆栈中清晰可见:所有那些包含gtk 的符号都是GTK+ Qt 样式。在大多数情况下,就性能分析或内存泄漏测试而言,这是个坏消息。

像 myprogram -style Fusion 这样启动你的程序 - 这样GTK+ 样式就不会被使用。

例如,在 valgrind 下启动它:

valgrind myprogram -style Fusion

您不想与自己的代码一起修复 GTK 和 Qt/GTK 互操作层错误 :)

【讨论】:

  • 谢谢,但我到底应该怎么做?这里真的是 linux 新手 :(
  • 你有没有像program -style Fusion一样开始你的程序?当然用你的程序真正拥有的任何名称替换program。
  • 以 fusion 样式运行仍然会出现相同的泄漏错误,我会稍后再查看,因为现在是午夜了
  • 但是你不应该再崩溃了。至少回溯应该有很大的不同。 QGtk 风格的插件代码中不应该有“泄漏”,因为您将不再使用该插件。无论如何,您得到的“泄漏”并不是真正的泄漏。
  • 不,不应该,但我发现问题不在于 gtk。刚运行 callgrind 程序就崩溃了,在vmwgfx_dri.so 和libGLX_mesa.so.0.0.0 中报告内存问题。然后我意识到这是一个 VMware 问题,很可能与 3d 加速有关,取消选中“加速 3D 图形”可以解决所有问题 :) 感谢您的提示,如果没有显示问题的另一个方面,我可能会死去检查我的代码
猜你喜欢
  • 1970-01-01
  • 2020-09-17
  • 1970-01-01
  • 2015-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-27
  • 2017-07-17
相关资源
最近更新 更多