2013-05-20 33 views
7

Vì vậy ... Tôi đang cố gắng loại bỏ một số rò rỉ bộ nhớ khỏi chương trình GTK + 3 của tôi. Tôi mặc dù nó sẽ là một ý tưởng tốt để nhìn lại một số ví dụ đơn giản để xem nếu có một số công cụ dọn dẹp tôi quên, nhưng chương trình hello_world được cung cấp trong tài liệu cũng bị rò rỉ. (Sản lượng Valgrind dưới đây).Rò rỉ bộ nhớ trong chương trình hello_world GTK

Những rò rỉ này có được chấp nhận không? Nếu vậy, có một số ứng dụng khác tôi nên sử dụng để gỡ lỗi chương trình GTK không?

==13717== Memcheck, a memory error detector 
==13717== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. 
==13717== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info 
==13717== Command: ./a 
==13717== 
Hello World 
==13717== 
==13717== HEAP SUMMARY: 
==13717==  in use at exit: 1,578,162 bytes in 11,614 blocks 
==13717== total heap usage: 45,699 allocs, 34,085 frees, 6,461,970 bytes allocated 
==13717== 
==13717== LEAK SUMMARY: 
==13717== definitely lost: 2,560 bytes in 5 blocks 
==13717== indirectly lost: 6,656 bytes in 207 blocks 
==13717==  possibly lost: 363,228 bytes in 1,937 blocks 
==13717== still reachable: 1,205,718 bytes in 9,465 blocks 
==13717==   suppressed: 0 bytes in 0 blocks 
==13717== Rerun with --leak-check=full to see details of leaked memory 
==13717== 
==13717== For counts of detected and suppressed errors, rerun with: -v 
==13717== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2) 

Code:

#include <gtk/gtk.h> 

/* This is a callback function. The data arguments are ignored 
* in this example. More on callbacks below. 
*/ 
static void 
print_hello (GtkWidget *widget, 
      gpointer data) 
{ 
    g_print ("Hello World\n"); 
} 

static gboolean 
on_delete_event (GtkWidget *widget, 
       GdkEvent *event, 
       gpointer data) 
{ 
    /* If you return FALSE in the "delete_event" signal handler, 
    * GTK will emit the "destroy" signal. Returning TRUE means 
    * you don't want the window to be destroyed. 
    * 
    * This is useful for popping up 'are you sure you want to quit?' 
    * type dialogs. 
    */ 

    g_print ("delete event occurred\n"); 

    return TRUE; 
} 

int 
main (int argc, 
     char *argv[]) 
{ 
    /* GtkWidget is the storage type for widgets */ 
    GtkWidget *window; 
    GtkWidget *button; 

    /* This is called in all GTK applications. Arguments are parsed 
    * from the command line and are returned to the application. 
    */ 
    gtk_init (&argc, &argv); 

    /* create a new window, and set its title */ 
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 
    gtk_window_set_title (GTK_WINDOW (window), "Hello"); 

    /* When the window emits the "delete-event" signal (which is emitted 
    * by GTK+ in response to an event coming from the window manager, 
    * usually as a result of clicking the "close" window control), we 
    * ask it to call the on_delete_event() function as defined above. 
    * 
    * The data passed to the callback function is NULL and is ignored 
    * in the callback function. 
    */ 
    g_signal_connect (window, "delete-event", G_CALLBACK (on_delete_event), NULL); 

    /* Here we connect the "destroy" event to the gtk_main_quit() function. 
    * 
    * This signal is emitted when we call gtk_widget_destroy() on the window, 
    * or if we return FALSE in the "delete_event" callback. 
    */ 
    g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); 

    /* Sets the border width of the window. */ 
    gtk_container_set_border_width (GTK_CONTAINER (window), 10); 

    /* Creates a new button with the label "Hello World". */ 
    button = gtk_button_new_with_label ("Hello World"); 

    /* When the button receives the "clicked" signal, it will call the 
    * function print_hello() passing it NULL as its argument. 
    * 
    * The print_hello() function is defined above. 
    */ 
    g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL); 

    /* The g_signal_connect_swapped() function will connect the "clicked" signal 
    * of the button to the gtk_widget_destroy() function; instead of calling it 
    * using the button as its argument, it will swap it with the user data 
    * argument. This will cause the window to be destroyed by calling 
    * gtk_widget_destroy() on the window. 
    */ 
    g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window); 

    /* This packs the button into the window. A GtkWindow inherits from GtkBin, 
    * which is a special container that can only have one child 
    */ 
    gtk_container_add (GTK_CONTAINER (window), button); 

    /* The final step is to display this newly created widget... */ 
    gtk_widget_show (button); 

    /* ... and the window */ 
    gtk_widget_show (window); 

    /* All GTK applications must have a gtk_main(). Control ends here 
    * and waits for an event to occur (like a key press or a mouse event), 
    * until gtk_main_quit() is called. 
    */ 
    gtk_main(); 

    return 0; 
} 

Trả lời

4

Câu trả lời này được biên dịch từ câu trả lời cho những câu hỏi tương tự (trên hiện nay không còn tồn tại www.gtkforums.com).

GTK + là khá lười khi nói đến phân bổ và deallocating bộ đệm bên trong cần thiết cho thời gian sống của ứng dụng. Ví dụ, nó có thể phân bổ một vùng bộ nhớ cho một bảng tra cứu trong quá trình khởi tạo cần thiết cho tuổi thọ của ứng dụng. GTK + sau đó sẽ không bao giờ deallocate này. Để Valgrind này trông giống như một rò rỉ bộ nhớ, (mà về mặt kỹ thuật nó là) nhưng như là một tối ưu hóa GTK + không deallocate nó vì nó sẽ được deallocated trong quá trình thoát ứng dụng và do đó không phải là một lỗi. Đây là lý do tại sao bạn cần các tập tin đàn áp để Valgrind có thể bỏ qua chúng. Vấn đề là bạn sẽ cần phải thay đổi chúng với hầu hết các thay đổi phiên bản GTK +.

Repository của file ức chế: https://github.com/dtrebbien/GNOME.supp

Sau khi nhân bản kho, bạn có thể tạo các file ức chế (cũng đi kèm với lém lỉnh, gdk, và những người khác) với "làm" và sau đó tham khảo valgrind với họ như như vậy:

valgrind ./a --suppression=/path/to/gtk3.supp 
+0

Tôi không hiểu cách sử dụng điều đó một cách đáng tin cậy. Tôi đã biên dịch mã của bạn trong câu hỏi bằng 'gcc -g -Wall $ (pkg-config --cflags gtk + -3.0) bill.c $ (pkg-config --libs gtk + -3.0) -o bill'. Tôi đã xây dựng dtrebbien/GNOME.supp và cài đặt tất cả các tệp '* supp' vào'/usr/lib/valgrind/'. Tôi chạy ví dụ của bạn với 'valgrind -v --suppressions =/usr/lib/valgrind/{base, glib, gio, gdk, gtk, gtk3} .supp./Bill' và valgrind vẫn hiển thị lỗi.Vui lòng giải thích thêm (với GTK3.22 trên Debian/Sid/x86-64, valgrind 3.12) –

1

Đối gỡ lỗi chương trình lém lỉnh/gtk Tôi sẽ sử dụng lệnh này:

G_SLICE=debug-blocks valgrind --tool=memcheck --leak-check=full <gtk program> 

G_SLICE = debug-khối sẽ tắt quản lý bộ nhớ tiên tiến gtk để cho phép valgrind để hiển thị kết quả chính xác.

- kiểm tra lỗi = đầy đủ sẽ hiển thị dấu vết ngăn xếp cho các khối bộ nhớ bị rò rỉ.

Bạn cũng có thể sử dụng --show-reachable = yes để xem dấu vết ngăn xếp cho tất cả các khối bộ nhớ không được miễn phí khi chương trình thoát.

Ngoài ra còn có công cụ valgrind khối lượng theo dõi việc sử dụng bộ nhớ để hiển thị phần nào của chương trình đang sử dụng nhiều bộ nhớ nhất.

chương trình Run dưới khối núi:

G_SLICE=always-malloc valgrind --tool=massif --detailed-freq=2 --max-snapshots=400 --num-callers=20 <gtk program> 

Hiện kết quả:

ms_print massif.out.<pid> 
+1

Valgrind vẫn hiển thị bị mất 2560 khối với G_SLICE = debug-blocks. Tôi sẽ xem xét các dấu vết và xem liệu tôi có thể biết chúng đến từ đâu không. – Bill