簡體   English   中英

GTK2回調數據丟失(設置為0 /垃圾)

[英]GTK2 callback data getting lost (set to 0/garbage)

我正在GTK中制作類似OneNote的應用程序,但是在實現一些基本功能時遇到了問題。 我有一個用於加載要處理的文件的菜單按鈕,但是由於某些原因,GTK運行回調時不會將我發送給回調存儲的數據取回。 我使用GDB來跟蹤問題,似乎無論何時調用任何回調函數,無論將回調連接到信號時將其設置為什么,data參數始終為零。

這是我認為相關代碼的一些摘要,但是完整的源代碼在這里的GitHub存儲庫中

notekeeper.c(主程序邏輯文件。我創建主窗口,需要引用的其他小部件以及保存這些引用的數組。然后繼續設置菜單。)

/* Storage variables for some important widgets */
GtkWidget *topWindow;
GtkWidget *sectionNotebook;
GtkWidget *important[2];
...
/* Set up the main window */
topWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
...
/* Add the section notebook */
sectionNotebook = gtk_notebook_new();
...
/* Set up the menu */
important[0] = topWindow;
important[1] = sectionNotebook;
menuBar = setupMenu(important);

menu.c(在其中創建菜單欄並將回調鏈接到菜單按鈕的位置。我使用調試器進行檢查,並且當它們用作回調數據時,對主窗口和sectionNotebook的引用似乎仍然有效。 )

GtkWidget *setupMenu(GtkWidget **importantWidgets) {
    ...
    FileMenuItems[0] = gtk_menu_item_new_with_mnemonic("Open");
    g_signal_connect(FileMenuItems[0], "activate", 
        G_CALLBACK(fileMenuOpenCallback), 
        (gpointer)importantWidgets);
    ...
}

callbacks.c(我在其中實現各種小部件的小部件回調例程的地方。)這似乎是我遇到問題的地方...

gint fileMenuOpenCallback(GtkWidget *widget, GdkEvent *event, 
gpointer calldata) {
    GtkWidget *openNotebookDialog;
    char *filename;
    GtkWidget **importantWidgets = (GtkWidget**)calldata;

    openNotebookDialog = gtk_file_chooser_dialog_new("Open Notebook...", 
        GTK_WINDOW(importantWidgets[0]), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, 
        GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
        NULL);
    ...
}

我在回調的第三行以及代碼中的其他幾處放置了一個斷點,並使用gdb來查看某些變量的值。 這是我使用gdb時發生的情況:

GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
Reading symbols from bin/notekeeper...done.
(gdb) b notekeeper.c:46
Breakpoint 1 at 0x80490f3: file src/notekeeper.c, line 46.
(gdb) b menu.c:37
Breakpoint 2 at 0x804945b: file src/menu.c, line 37.
(gdb) b callbacks.c:38
Breakpoint 3 at 0x8049319: file src/callbacks.c, line 38.
(gdb) run
Starting program: [PROJECT DIRECTORY]/bin/notekeeper 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/i686/cmov/libthread_db.so.1".
Gtk-Message: Failed to load module "canberra-gtk-module"

Breakpoint 1, main (argc=1, argv=0xbffff3f4 "x\365\377\277")
    at src/notekeeper.c:46
46      topWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
(gdb) next
47      g_signal_connect(G_OBJECT(topWindow), "delete_event", 
(gdb) print topWindow
$1 = (GtkWidget *) 0x8072248
(gdb) continue
Continuing.

Breakpoint 2, setupMenu (importantWidgets=0xbffff324) at src/menu.c:37
37      FileMenuItems[0] = gtk_menu_item_new_with_mnemonic("Open");
(gdb) print importantWidgets
$2 = (GtkWidget **) 0xbffff324
(gdb) print importantWidgets[0]
$3 = (GtkWidget *) 0x8072248
(gdb) continue
Continuing.

Breakpoint 3, fileMenuOpenCallback (widget=0x80abc28, event=0xbffff324, 
    calldata=0x14) at src/callbacks.c:38
38      GtkWidget **importantWidgets = (GtkWidget**)calldata;
(gdb) p calldata
$4 = (gpointer) 0x14
(gdb) p (GtkWidget **)calldata
$5 = (GtkWidget **) 0x14
(gdb) p (GtkWidget **)calldata[0]
Attempt to dereference a generic pointer.
(gdb) continue
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x08049329 in fileMenuOpenCallback (widget=0x80abc28, event=0xbffff324, 
    calldata=0x14) at src/callbacks.c:42
42          GTK_WINDOW(importantWidgets[0]), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, 
(gdb) kill
Kill the program being debugged? (y or n) yes
(gdb) 

我們可以在斷點1處看到topWindow(這是我要在回調中使用的值)被設置為真實地址。 然后,在第二個斷點處,我們在setupMenu函數內部,在其中設置菜單欄並將信號連接到菜單的回調。

之后,該應用程序出現在屏幕上,然后單擊菜單上的“打開”按鈕,使它運行我的回調。 這是斷點3停止應用程序的地方。 您可以在此處看到我的數據的函數參數此時為0x14,並且不再指向我的小部件引用列表。 我什至像程序一樣將其轉換回適當的類型,並嘗試引用它,但是調試器不會這樣做。 因此,我繼續,程序嘗試使用該值,但是當然,它已損壞,並且由於嘗試訪問一些我不應該使用的內存而出現了段錯誤。

我不太擔心崩潰,因為我可以通過將NULL代替GTK_WINDOW(importantWidgets [0])來阻止崩潰,因為GTK_WINDOW(importantWidgets [0])應該是對我的根窗口的引用。 我主要關心的是為什么數據參數(在這種情況下為calldata)被設置為0x14。 當我將信號連接到回調時,我為它分配了一個完全不同的值,所以我不確定發生了什么。 GTK2中是否已棄用或刪除此數據參數? 還是功能正常,我使用錯了。 我只想知道GTK為何會如此。

為了檢驗我的理論,我什至在一些僅運行gtk_main_quit()的回調函數中添加了一些虛擬數據。 但是,當我使用GDB進行調試時,虛擬數據不存在。 再次將其設置為0或其他一些小數字。 因此問題似乎影響了所有GTK。

如果您有任何想法,請告訴我,我是GTK的新手,所以我想知道為什么它看起來像這樣不正常,以及這是我的錯還是GTK中的錯誤。 同樣,如果您需要仔細查看或自己運行,則完整的代碼位於Github存儲庫中。 它只需要autoconf,make,一個C編譯器,GTK2(不是3)和libxml2來構建和運行。

請參閱Johannes對原始帖子的評論。 事實證明,並非所有GTK信號都具有相同的回調函數參數。 這個沒有GDKEvent參數。 謝謝您的幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM