7

I'm trying to learn gtkmm, and decided to try gtkmm 2.4 for the time being since it seems to be pretty hard to get 3.0 working on Debian. Anyway, the example I'm trying is the one here: http://developer.gnome.org/gtkmm-tutorial/2.24/sec-helloworld.html.en. It compiles fine and it runs alright aswell, but when i close it valgrind reports a lot of leaks, something along the lines of this (after clicking the button once):

==4254== Memcheck, a memory error detector
==4254== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==4254== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==4254== Command: ./bin/jmb
==4254== 
Hello World
==4254== 
==4254== HEAP SUMMARY:
==4254==     in use at exit: 942,940 bytes in 7,968 blocks
==4254==   total heap usage: 14,191 allocs, 6,223 frees, 3,272,961 bytes allocated
==4254== 
==4254== LEAK SUMMARY:
==4254==    definitely lost: 2,620 bytes in 6 blocks
==4254==    indirectly lost: 5,936 bytes in 187 blocks
==4254==      possibly lost: 358,625 bytes in 1,775 blocks
==4254==    still reachable: 575,759 bytes in 6,000 blocks
==4254==         suppressed: 0 bytes in 0 blocks
==4254== Rerun with --leak-check=full to see details of leaked memory
==4254== 
==4254== For counts of detected and suppressed errors, rerun with: -v
==4254== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 9 from 9)

This happens if i stop the program with C-c or click the close window button (in this case i have to use Shift-Meta-C to close the window because of the window manager). Is this the expected behaviour like MySQL's connector that doesn't allow you to delete that one last pointer? In that case it seems like a lot of memory not being "allowed" to be deleted? Or am i just missing something really simple?

For the sake of it here's my code: (Changed HelloWorld to Test) main.cpp:

#include "gui/Test.hpp"
#include <gtkmm/main.h>
int main(int argc, char **argv)
{
  Gtk::Main kit(argc, argv);
  Test t;
  Gtk::Main::run(t);
  return 0;
}

Test.hpp:

#pragma once

#include <gtkmm/button.h>
#include <gtkmm/window.h>

class Test
  : public Gtk::Window
{
public:
  Test();
  virtual ~Test();

protected:
  //Signal handlers:
  void on_button_clicked();

  //Member widgets:
  Gtk::Button m_button;
};

Test.cpp:

#include "Test.hpp"
#include <iostream>

Test::Test()
  : m_button("Hello World")   // creates a new button with label "Hello World".
{
  // Sets the border width of the window.
  set_border_width(10);

  // When the button receives the "clicked" signal, it will call the
  // on_button_clicked() method defined below.
  m_button.signal_clicked().connect(sigc::mem_fun(*this,
              &Test::on_button_clicked));

  // This packs the button into the Window (a container).
  add(m_button);

  // The final step is to display this newly created widget...
  m_button.show();
}

Test::~Test()
{

}

void Test::on_button_clicked()
{
  std::cout << "Hello World" << std::endl;
}

Thanks in advance!

4

3 回答 3

3

考虑到您没有动态内存分配,泄漏不是来自您的代码。由于您Test t在堆栈上而不是动态地定义了变量,因此当它超出范围时将被删除。那将是 main() 函数完成的时候,实际上是在整个程序完成之前。Test 类也没有任何直接的动态内存分配。通过提及直接,我的意思是直接在该类中,而不是在它包含的属性(gtk 等)中。

为了证明您的 Test 实例确实被删除了,您可以在析构函数中放置一个 printf。当应用程序退出时,您应该会看到输出。

即使您已经动态定义/创建了 Test 实例,您也应该养成始终删除您创建的所有内容的习惯。在这种情况下,它只是内存,但它可能是更有价值的资源,如数据库连接、文件系统资源或其他需要在退出时执行的逻辑。

Valgrind 可以为您提供实际内存泄漏发生位置的堆栈跟踪,我很确定您会看到它们在 gtk 代码中。如果是这样,我会考虑提出一个错误。我不会太担心still reachable内存(它实际上不是泄漏),而是查看definitely lostand indirectly lost

于 2012-05-24T07:11:25.110 回答
2

假设 Gtk-- 不泄漏内存,您发布的输出可以与此假设兼容。

在程序退出时仍然可以访问一些内存的事实与内存泄漏不同。

以下程序是否泄漏内存?

int main() {
     int* a = new int[10];
     return 0;
}

看起来可能是这样,但完整的答案应该是:这取决于!

如果我们不使用 MS/DOS 并且直到程序结束都需要“a”,这很难定义为泄漏......我们可以说程序员将清理的责任留给了底层操作系统。

此外,Valgrind 是一个非常好的和有用的工具,但可以报告误报。

于 2012-05-22T19:14:45.720 回答
1

设置 G_SLICE 环境变量以重新配置 GSlice 内存分配器。

G_SLICE=always-malloc ./your_application

详情请看这篇文章

于 2012-05-18T17:40:34.310 回答