GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Mon Dec 22, 2014 10:05 pm

All times are UTC




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: Memory leak when removing objects
PostPosted: Mon Sep 23, 2013 7:55 pm 
Offline

Joined: Fri Sep 20, 2013 9:03 pm
Posts: 2
Greetings,
While searching for a memory leak in a large project, I've been using the following program to test the various bits for leaks. After narrowing the leak to a single function call, I began passing each piece of the function through this piece of code. I'm using Gtk version 2.24.20 and Glib version 2.36.4.
From what I've found, the following leaks memory:

Code:
#include <iostream>
#include "gtkmm.h"
#include "iostream"
#include "malloc.h"
using namespace std;

class MemTracker {  //ease-of-use memory output
public:
  struct mallinfo info;
  MemTracker(): info(mallinfo()) { }
  void reportChange(bool update) {
    struct mallinfo snapshot = mallinfo();
    cout << "Change--Arena: " << snapshot.arena-info.arena << " Free: " << snapshot.fordblks-info.fordblks << " Used: " << snapshot.uordblks-info.uordblks << endl;
    if(update) { info = snapshot; }
  }
  void mark() {
    info = mallinfo();
  }
  void print(const char * prefix) {
    cout << prefix << "-Arena: " << info.arena << " Free: " << info.fordblks << " Used: " << info.uordblks << endl;
  }
};

int main(int argc, char* argv[])
{
  Glib::init();
  cout << "Glib version:  " <<  glib_major_version << "." << glib_minor_version << "." << glib_micro_version << endl;
  cout << "Gtk version:  " << gtk_major_version << "." << gtk_minor_version << "." << gtk_micro_version << endl;
  MemTracker tracker;
  Gtk::Table *box = new Gtk::Table;
  while(true) {
    Gtk::Label &testLabel = *Gtk::manage(new Gtk::Label);
    testLabel.show();
    box->attach(testLabel, 1, 2, 1, 2);
    tracker.mark();
    tracker.print("Before");
    box->remove(testLabel);
    delete &testLabel;
    tracker.reportChange(true);
    tracker.print("After");
    sleep(argc>1 ? atoi(argv[1]) : 2);
  }
  delete box;
  return 0;
}


The section up at the top is simply a wrapper for various native memory tracking and reporting stuff. The output of this program looks like this:

Code:
Glib version:  2.36.4
Gtk version: 2.24.20
Before-Arena: 135168 Free: 54112 Used: 81056
Change--Arena: 0 Free: -704 Used: 704
After-Arena: 135168 Free: 53408 Used: 81760

Before-Arena: 135168 Free: 53136 Used: 82032
Change--Arena: 0 Free: -80 Used: 80
After-Arena: 135168 Free: 53216 Used: 81952

Before-Arena: 135168 Free: 52994 Used: 82224
Change--Arena: 0 Free: -80 Used: 80
After-Arena: 135168 Free: 53024 Used: 82114

Before-Arena: 135168 Free: 52752 Used: 82416
Change--Arena: 0 Free: -80 Used: 80
After-Arena: 135168 Free: 523832 Used: 82336

Before-Arena: 135168 Free: 52560 Used: 82608
Change--Arena: 0 Free: -80 Used: 80
After-Arena: 135168 Free: 52640 Used: 82528

Before-Arena: 135168 Free: 52368 Used: 82800
Change--Arena: 0 Free: -80 Used: 80
After-Arena: 135168 Free: 52448 Used: 82720

Before-Arena: 135168 Free: 52176 Used: 82992
Change--Arena: 0 Free: -80 Used: 80
After-Arena: 135168 Free: 52256 Used: 82912


I've tested this code with simple 'new' and 'delete' without attaching testLabel to anything or removing it. There is no rise in the Used number. Also, I've removed the sleep() call at the end of the code and watched its memory use through top--it also rises rapidly.
Am I misusing one of these functions in here? The documentation on remove() tells me I should be calling delete on whatever I call remove() on, but regardless of if I delete the object or use Gtk::manage() on it, I get the same behavior.
Any help would be greatly appreciated!


Top
 Profile  
 
 Post subject: Re: Memory leak when removing objects
PostPosted: Thu Sep 26, 2013 6:10 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 799
Location: UK
Hello,

Your code has many mistakes in it.

- You have initialised Glib but you have not initialised GTK
- At no point have you given control to the GTK+ main-loop, so signals can not be called

GTK delays many things by using signals. This helps with speed by grouping like or repeated operations together or the appearance of speed by doing things when nothing else is needed to be done.

These can include drawing to the screen, storing text, scrolling, completing a widget destruction and freeing memory.
Although not correct by adding the following code to you loop we then enter the GTK main loop. (Note I could not compile your code)
Code:
    while (g_main_context_pending(NULL))
        g_main_context_iteration(NULL, FALSE);


Also note that GTK and GLib do memory caching so the use of some low level memory tools may give false readings if not used with care.

You may want to read the documentation here https://developer.gnome.org/glib/stable/glib-Memory-Allocation.html and https://developer.gnome.org/glib/stable/glib-running.html.

_________________
E.


Top
 Profile  
 
 Post subject: Re: Memory leak when removing objects
PostPosted: Thu Sep 26, 2013 9:24 pm 
Offline

Joined: Fri Sep 20, 2013 9:03 pm
Posts: 2
Greetings,
What error(s) are you getting when you try to compile it? It compiles without warnings for me.
I inserted the loop statement and initialized gtk with gtk_init() at the beginning of my program (whoops--we were already doing that in the larger program I referenced earlier, just forgot to here). As of now, the code looks like this:

Code:
#include "gtkmm.h"
#include "iostream"
#include "malloc.h"

using namespace std;

class MemTracker {  //ease-of-use memory output
public:
  struct mallinfo info;
  MemTracker(): info(mallinfo()) { }
  void reportChange(bool update) {
    struct mallinfo snapshot = mallinfo();
    cout << "Change--Arena: " << snapshot.arena-info.arena << " Free: " << snapshot.fordblks-info.fordblks << " Used: " << snapshot.uordblks-info.uordblks << endl;
    if(update) { info = snapshot; }
  }
  void mark() {
    info = mallinfo();
  }
  void print(const char * prefix) {
    cout << prefix << "-Arena: " << info.arena << " Free: " << info.fordblks << " Used: " << info.uordblks << endl;
  }
};

int main(int argc, char* argv[])
{

  int w = 1;
  Glib::init();
  gtk_init(&argc, &argv);
  cout << "Glib version:  " <<  glib_major_version << "." << glib_minor_version << "." << glib_micro_version << endl;
  cout << "Gtk version:  " << gtk_major_version << "." << gtk_minor_version << "." << gtk_micro_version << endl;
  MemTracker tracker;
       while (g_main_context_pending(NULL)) {
        g_main_context_iteration(NULL, FALSE);
  auto *box = new Gtk::VBox;

  while(true){

    Gtk::Label &testLabel = *manage(new Gtk::Label);
    testLabel.show();
    box->add(testLabel);
    tracker.mark();
    tracker.print("Before");
    box->remove(testLabel);
    delete &testLabel;
    tracker.reportChange(true);
    tracker.print("After");

    if(w){
      sleep(argc>1 ? atoi(argv[1]) : 2);
      w = 0;
    }
    sleep(2);
  }
  }
  return 0;
}


However, the behavior is unchanged. Upon playing with it further, if I remove the call to manage() and use new and delete on the testLabel object instead, it stops leaking. I've tried using manage() both with the delete statement at the bottom and without it. When I've manage()d the contents of testLabel, the program leaks memory. As I said before, I can observe the leak through the top utility as well as the diagnostic I've inserted. Am I making any errors here other than the two you listed? I'd appreciate any further assistance--I'd like to be able to rule this sort of thing out as a culprit for the memory leak my team is trying to fix.


Top
 Profile  
 
 Post subject: Re: Memory leak when removing objects
PostPosted: Fri Sep 27, 2013 6:18 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 799
Location: UK
Hope the following code works for you.

My technical problem was that I had a linking problem that is now solved along with the original example.

Your mistake was the incorrect use of reference variables and Gtk::manage().

Here technically you do not need to use Gtk::manage() or Gtk::Container::remove() as you are explicitly using delete to delete the Gtk::Label widget.

https://developer.gnome.org/gtkmm-tutorial/stable/sec-memory-widgets.html.en Gives more information on memory management with widgets. This is for gtkmm v3 though it is the same for v2.

Code:
#include "gtkmm.h"
#include "iostream"
#include "malloc.h"

class MemTracker {  //ease-of-use memory output
public:
  struct mallinfo info;
  MemTracker(): info(mallinfo()) { }
  void reportChange(bool update) {
    struct mallinfo snapshot = mallinfo();
    std::cout << "Change--Arena: " << snapshot.arena-info.arena << " Free: " << snapshot.fordblks-info.fordblks << " Used: " << snapshot.uordblks-info.uordblks << std::endl;
    if(update) { info = snapshot; }
  }
  void mark() {
    info = mallinfo();
  }
  void print(const char * prefix) {
    std::cout << prefix << "-Arena: " << info.arena << " Free: " << info.fordblks << " Used: " << info.uordblks << std::endl;
  }
};

int main(int argc, char* argv[])
{

  int w = 1;
  Gtk::Main kit(&argc, &argv);

  std::cout << "Glib version:  " <<  glib_major_version << "." << glib_minor_version << "." << glib_micro_version << std::endl;
  std::cout << "Gtk version:  " << gtk_major_version << "." << gtk_minor_version << "." << gtk_micro_version << std::endl;
  MemTracker tracker;

  Gtk::VBox *box = new Gtk::VBox;

  while(true){

    Gtk::Label *testLabel = manage(new Gtk::Label);
    testLabel->show();
    box->add(*testLabel);
    tracker.mark();
    tracker.print("Before");
//   box->remove(*testLabel);
    delete testLabel;
    tracker.reportChange(true);
    tracker.print("After");

       while (g_main_context_pending(NULL)) {
        g_main_context_iteration(NULL, FALSE);

    if(w){
      sleep(argc>1 ? atoi(argv[1]) : 2);
      w = 0;
    }
    sleep(2);
  }
  }
  return 0;
}

_________________
E.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group