After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 394907 - delete the class which inherit from gtk has some memory leak.
delete the class which inherit from gtk has some memory leak.
Status: RESOLVED INVALID
Product: gtkmm
Classification: Bindings
Component: general
2.8.x
Other All
: Normal critical
: ---
Assigned To: gtkmm-forge
gtkmm-forge
Depends on:
Blocks:
 
 
Reported: 2007-01-10 02:31 UTC by simon
Modified: 2007-02-11 10:48 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description simon 2007-01-10 02:31:57 UTC
Please describe the problem:
I am a newly programmer of glibmm . I wrote some picture button widget for media center application.But it has serious memory leak. then I worte a test program to simulate the case of my programe, the leak problem still has. Following section is my test program and library version which I used. Whether is the glibmm's bug or my incorrect using of glibmm?
Any adivce is appreciate. Thanks very much! :)


linux-fusion	3.0
DirectFB	0.9.25
pkg-config	0.20
glib		2.10.2
ATK		1.10.3
cairo		1.0.2
Pango		1.12.2
GTK+(/DFB)	2.8.10
Libsigc++	2.0.17
glibmm		2.8.7
Gtkmm		2.8.7

/* compiler.sh */
#!/bin/sh

export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:/usr/gtkdfb/lib/pkgconfig"
export LD_LIBRARY_PATH="/usr/local/lib/:/usr/gtkdfb/lib/"

rm testpv -rf
rm pagevideo.o -rf
rm examplewindow.o -rf

g++ -c pagevideo.cc `pkg-config gtkmm-2.4 --cflags`
g++ -c examplewindow.cc `pkg-config gtkmm-2.4 --cflags`

g++ main.cc -o testpv pagevideo.o examplewindow.o `pkg-config gtkmm-2.4 --cflags --libs` -DREENTRANT -O3 -fexpensive-optimizations -ffast-math -Wall -g0 -L/usr/gtkdfb/lib  



/* pagevideo.h */
#ifndef _PAGEVIDEO_H_
#define _PAGEVIDEO_H_
#include <glibmm.h>
#include <gtkmm.h>
#include <gdkmm.h>
using namespace Gtk;
using namespace Glib;
using namespace Gdk;

typedef sigc::signal<void, int> MEVENT_PAGEBTN;

class MPageVideo:public Gtk::Fixed
{
  private:
    bool OnButtonKeyPress(GdkEventKey *ev);
    bool OnButtonPress(GdkEventButton *ev);
    bool on_mdrawArea_expose_event(GdkEventExpose *ev);
  private:

    DrawingArea * mdrawArea;
    EventBox    * meventBox;

    MEVENT_PAGEBTN m_signal;

    int mLeft;
    int mTop;
    int mWidth;
    int mHeight;
    int mpieces;
  public:
    MEVENT_PAGEBTN signal_something();
    void showbg();
    void hide();
    void show();
    MPageVideo();
    ~MPageVideo();
};


/* pagevideo.cc */

#include <time.h>
#include <sys/timeb.h>

#include "pagevideo.h"

MPageVideo::MPageVideo()
{
  mWidth = 273;
  mpieces = 1;
  mHeight = 47;
  mLeft = 0;
  mTop = 196;

  meventBox = new class Gtk::EventBox();
  mdrawArea = new class Gtk::DrawingArea();

  mdrawArea->set_size_request(mWidth/mpieces, mHeight);
  meventBox->set_flags(Gtk::CAN_FOCUS);
  meventBox->set_size_request(mWidth/mpieces, mHeight);
  meventBox->add(*mdrawArea);
  put (*meventBox, mLeft, mTop);

  mdrawArea->add_events(ALL_EVENTS_MASK);

  /* user click/press the meventBox to notify the app which use the pagevideo class to delete it */
  meventBox->signal_button_press_event().connect (sigc::mem_fun(*this, &MPageVideo::OnButtonPress));
  meventBox->signal_key_release_event().connect (sigc::mem_fun(*this, &MPageVideo::OnButtonKeyPress), false);
  mdrawArea->signal_expose_event().connect(sigc::mem_fun(*this, &MPageVideo::on_mdrawArea_expose_event), false);
  meventBox->signal_expose_event().connect(sigc::mem_fun(*this, &MPageVideo::on_mdrawArea_expose_event), false);
  meventBox->show();
  mdrawArea->show();
  meventBox->grab_focus();

}

MEVENT_PAGEBTN MPageVideo::signal_something()
{
  return m_signal;
}

bool MPageVideo::on_mdrawArea_expose_event(GdkEventExpose *ev)
{
  RefPtr<Gdk::GC> gc;
  RefPtr<Gdk::Window> mwindow;

  mwindow = mdrawArea->get_window();
  gc = Gdk::GC::create(mwindow);
  mwindow->draw_line(gc, 1, 1, 150, 1);
  mwindow->draw_line(gc, 1, 20, 150, 20);
  mwindow->draw_line(gc, 1, 1, 1, 20);
  mwindow->draw_line(gc, 150,1 , 150, 20);

  return true;
}

bool MPageVideo::OnButtonPress(GdkEventButton *ev)
{

  hide();
  m_signal.emit(1);
  return true;

}

void MPageVideo::showbg()
{
}

void MPageVideo::hide()
{
  Fixed::hide();
}
void MPageVideo::show()
{
  Fixed::show();
  meventBox->show();
  mdrawArea->show();
}

bool MPageVideo::OnButtonKeyPress(GdkEventKey *ev)
{
  hide();
  m_signal.emit (1);
  return true;
}

MPageVideo::~MPageVideo()
{
/*
  meventBox->remove();
  Gtk::Container::remove (*meventBox);
 */
  delete meventBox;
  delete mdrawArea;
}


/* examplewindow.h */#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H

#include <gtkmm.h>
#include "pagevideo.h"

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

protected:
  //Signal handlers:
  virtual void on_button_quit();
  virtual void on_button_test();
          void on_page_close(int val);

  //Child widgets:
  Gtk::VBox m_VBox;
  int press_count;
  MPageVideo *PageVideo;
  Gtk::HButtonBox m_ButtonBox;
  Gtk::Table m_Table; 
  Gtk::Button m_Button_Quit;
  Gtk::Button m_Button_Test;
  Gtk::Notebook notebook;
  class Gtk::Alignment m_align;

};

#endif //GTKMM_EXAMPLEWINDOW_H


/* examplewindow.cc */

#include <iostream>
#include "examplewindow.h"

ExampleWindow::ExampleWindow()
  : m_Button_Quit("Quit"),
  m_Button_Test("Test"),
  m_align(Gtk::ALIGN_LEFT, Gtk::ALIGN_TOP, 0.0, 0.0)
{
  set_title("Custom Container example");
  set_border_width(6);
  set_default_size(800, 600);
  press_count = 0;
  add(m_VBox);
  notebook.append_page (m_align);
  m_VBox.pack_start(notebook, Gtk::PACK_EXPAND_WIDGET);
  m_VBox.pack_start(m_ButtonBox, Gtk::PACK_SHRINK);

  m_ButtonBox.pack_start(m_Button_Test, Gtk::PACK_SHRINK);
  m_ButtonBox.pack_start(m_Button_Quit, Gtk::PACK_SHRINK);
  

  m_ButtonBox.set_border_width(6);
  m_ButtonBox.set_layout(Gtk::BUTTONBOX_END);
  m_Button_Quit.signal_clicked().connect( sigc::mem_fun(*this, &ExampleWindow::on_button_quit) );
  m_Button_Test.signal_clicked().connect( sigc::mem_fun(*this, &ExampleWindow::on_button_test) );
  show_all_children();
}

ExampleWindow::~ExampleWindow()
{
}



void ExampleWindow::on_page_close(int val)
{
  fprintf (stderr, "on_page_close!\n");
  Gtk::Container::remove (*PageVideo);
  delete PageVideo;
  PageVideo = NULL;
}

void ExampleWindow::on_button_test()
{
  fprintf (stderr, "button_test pressed\n");
  if (!PageVideo) {
    PageVideo = new class MPageVideo ();
    PageVideo->signal_something().connect (sigc::mem_fun (*this, &ExampleWindow::on_page_close));
    PageVideo->show();
    m_align.add (*PageVideo);
    show_all_children();
    press_count++;
    fprintf (stderr, "MPageVideo created %d times\n", press_count);
  }
}

void ExampleWindow::on_button_quit()
{
  hide();
}


/* main.cc */
#include <gtkmm/main.h>
#include "examplewindow.h"

int main(int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);

  ExampleWindow window;
  Gtk::Main::run(window); //Shows the window and returns when it is closed.

  return 0;
}

Steps to reproduce:
1. when app build done , run it.
2. use test button to create MPageVideo class.
3. when create MPageVideo done, click the rectangle to delete it.
4. repeat the prior operation about 100 times. 

Actual results:
the amount memory leak will be about 7M. use free to trace.


Expected results:
I expect there no memory leak.

Does this happen every time?
lost some memory

Other information:
The test platform of software is Fodero Core 4. 
The architecture I used is gtkmm/gtk+ for directfb/directfb/linux frame buffer.
Comment 1 Murray Cumming 2007-01-28 14:34:11 UTC
Could you please give more details, maybe from a valgrind run. And could you please simplify your example.
Comment 2 Murray Cumming 2007-02-10 12:01:07 UTC
Furthermore, I see no rectangle as described in your step 3.

Please simplify your test case to a single simple-as-possible .cc file and attach it, after reopening this bug. I want to help but I'm not prepared to do all your debugging for you.
Comment 3 simon 2007-02-11 05:51:27 UTC
(In reply to comment #2)
> Furthermore, I see no rectangle as described in your step 3.
> 
> Please simplify your test case to a single simple-as-possible .cc file and
> attach it, after reopening this bug. I want to help but I'm not prepared to do
> all your debugging for you.
> 

Thank you for your reply.

It may gtk+ not properly to use directfb . I thanged the gtk source code as follow:
gdkwindow-directfb.c
void
_gdk_windowing_window_destroy (GdkWindow *window,
                               gboolean   recursing,
                               gboolean   foreign_destroy)
{
  GdkWindowObject       *private;
  GdkWindowImplDirectFB *impl;

  g_return_if_fail (GDK_IS_WINDOW (window));

  private = GDK_WINDOW_OBJECT (window);
  impl = GDK_WINDOW_IMPL_DIRECTFB (private->impl);

  _gdk_selection_window_destroyed (window);

  if (window == _gdk_directfb_pointer_grab_window)
    gdk_pointer_ungrab (GDK_CURRENT_TIME);
  if (window == _gdk_directfb_keyboard_grab_window)
    gdk_keyboard_ungrab (GDK_CURRENT_TIME);

  if (window == gdk_directfb_focused_window)
    gdk_directfb_change_focus (NULL);

  if (!recursing && !foreign_destroy && impl->window ) {
    	impl->window->SetOpacity (impl->window,0);
   		impl->window->Close(impl->window);
      	impl->window->Release(impl->window);
  }

  /* follow line is added by simon that refers from debian installer
   * this change make the leak very samller , but it still has.
   */
  g_object_unref (window);

#if 0 /* let the finalizer kill it */
  if (!recursing && !foreign_destroy)
    {
  		if (impl->window)
    		impl->window->Destroy (impl->window);
  		impl->window = NULL;
	}
#endif
}

I am not familiar with the gtk source. I think may be the some directfb surface or widow ref not properly destroy. If you have any good idea, let me know , thank you ! 

Comment 4 Murray Cumming 2007-02-11 10:48:47 UTC
> It may gtk+ not properly to use directfb . I thanged the gtk source code as
> follow:

1. That's not a patch (try "svn diff"), so it's not easy to see what you changed.
2. If a fix is necessary in GTK+ then please submit a patch to a GTK+ bug. Please do mention the bug number here.
3. I am surprised that DirectFB is relevant here, but even for fixing a DirectFB problem, you need a simple test case to demonstrate the problem. This test case is not simple enough.