7

私はgtkmmを学ぼうとしていますが、Debianで3.0を動作させるのはかなり難しいように思われるので、とりあえずgtkmm2.4を試してみることにしました。とにかく、私が試している例はここにあります:http: //developer.gnome.org/gtkmm-tutorial/2.24/sec-helloworld.html.en。正常にコンパイルされ、正常に実行されますが、閉じると、valgrindは多くのリークを報告します。これは、(ボタンを1回クリックした後)次のようなものです。

==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)

これは、Ccでプログラムを停止するか、ウィンドウを閉じるボタンをクリックした場合に発生します(この場合、ウィンドウマネージャーのためにShift-Meta-Cを使用してウィンドウを閉じる必要があります)。これは、最後の1つのポインタを削除できないMySQLのコネクタのような予想される動作ですか?その場合、多くのメモリが「削除」されていないように見えますか?それとも私は本当に単純なものを見逃していますか?

そのために、ここに私のコードがあります:( HelloWorldをテストに変更しました)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;
}

前もって感謝します!

4

3 に答える 3

3

動的なメモリ割り当てがないことを考えると、リークはコードからではありません。変数は動的ではなくスタックで定義Test tしたため、スコープ外になると削除されます。これは、main()関数が完了するときであり、実際にはプログラム全体が完了する前です。また、Testクラスには直接動的メモリ割り当てはありません。直接言及するということは、そのクラスに直接言及することを意味しますが、それに含まれる属性(gtkなど)には含まれません。

テストインスタンスが実際に削除されていることを示すために、デストラクタにprintfを配置できます。アプリケーションが終了すると、出力が表示されます。

テストインスタンスを動的に定義/作成した場合でも、作成したものはすべて常に削除する習慣を身に付ける必要があります。この場合は単なるメモリですが、DB接続、ファイルシステムリソース、または終了時に実行する必要のあるその他のロジックなど、より価値のあるリソースである可能性があります。

Valgrindは、実際のメモリリークが発生した場所のスタックトレースを提供する可能性があります。これらがgtkコードに含まれていることがわかると思います。もしそうなら、私はバグを提起することを検討します。still reachable私はメモリ(実際にはリークではありません)についてはあまり気にしませんが、代わりにdefinitely lostとを調べます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 に答える