集成测试的时候发现一个程序在持续的运行过程中有缓慢的内存增长。用ValGrind来查并没有太多的发现。询问开发人员的时候,他说GTK的内存好象都有一些泄露,网上有文曰
If GtkFoo isn't a toplevel window, then
foo = gtk_foo_new ();
gtk_widget_destroy (foo);
is a memory leak。
这个我是不相信的,于是有了两个内存泄露的问题需要解释。
1、我们的程序为什么内存泄露?在放弃了工具帮忙后,逐段代码注释,注释后并细心观察内存半个小时后记录内存起伏情况。最后发现我们的代码确实有问题。
GList *list_child;
......
list_child=gtk_container_get_children (GTK_CONTAINER (button));
fixed=GTK_WIDGET(list_child->data);
list_child=gtk_container_get_children (GTK_CONTAINER (fixed));
image=GTK_WIDGET(list_child->data);
shadow=button_array_item->shadow;
我们想当然认为list_child不用释放,是容器内部管理的GList列表,实际上,文档明确说返回值是一个newly-allocated的list :
gtk_container_get_children ()
GList * gtk_container_get_children (GtkContainer *container);
Returns the container's non-internal children. See gtk_container_forall()
for details on what constitutes an "internal" child.
| a GtkContainer |
Returns : | a newly-allocated list of the container's non-internal children. |
2、同事说的例子为什么有内存泄露?找了文章看到下面的解释
1.5. | Why does my program leak memory, if I destroy a widget immediately after creating it ? |
If GtkFoo isn't a toplevel window, then foo = gtk_foo_new (); is a memory leak, because no one assumed the initial floating reference. If you are using a widget and you aren't immediately packing it into a container, then you probably want standard reference counting, not floating reference counting. To to get this, you must acquire a reference to the widget and drop the floating reference (“ref and sink ” in GTK+ parlance) after creating it: foo = gtk_foo_new (); When you want to get rid of the widget, you must call gtk_widget_destroy() to break any external connections to the widget before dropping your reference: gtk_widget_destroy (foo); When you immediately add a widget to a container, it takes care of assuming the initial floating reference and you don't have to worry about reference counting at all ... just call gtk_widget_destroy() to get rid of the widget. |