最近遇到一個不錯的小例子, 可以比較完整地記錄用到的相關指令。更多關於 gdb 的說明, 見 gdb 初步心得。
問題
Ubuntu 下執行程式後看到 "Gtk-WARNING **: cannot open display:", 然後程式就掛了。
解決過程
為了獲取更多線索, 我想找出是那段程式輸出這個錯誤訊息。由 "Gtk-WARNING" 可知是 Gtk+ 函式庫輸出的錯誤訊息。所以得先取得 Gtk+ 的 debug symbol 和原始碼:
$ dpkg -l | grep gtk ... ii libgtk2.0-0 ...
找出已安裝的 Gtk+ 函式庫叫做 libgtk2.0, 接著找出它對應的 debug symbol package 和原始碼:
$ aptitude search libgtk2.0 i libgtk2.0-0 - GTK+ graphical user interface library ... i libgtk2.0-0-dbg - GTK+ libraries and debugging symbols ... i libgtk2.0-dev - development files for the GTK+ library ...
然後安裝 debug symbol, 還有取得 Gtk+ 的原始碼:
$ aptitude install libgtk2.0-0-dbg $ apt-get source libgtk2.0-dev
從取得的原始碼找看看有沒有 "cannot open display":
$ cd gtk+2.0-2.24.10/ $ grep "cannot open display" -R . ./gtk/gtkmain.c: g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : ""); ./gdk/gdk.c: g_warning ("cannot open display: %s", display_name ? display_name : ""); ./.pc/071_no_offscreen_widgets_grabbing.patch/gtk/gtkmain.c: g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : ""); ./.pc/100_overlay_scrollbar_loading.patch/gtk/gtkmain.c: g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : ""); ./ChangeLog.pre-2-12: * gtk/gtkmain.c: (gtk_init): Fix "cannot open display" error message
讀一下字串出現相關的位置, 找出函式 gtk_init_check 和 gdk_init_check。看來沒有找錯方向, 於是可以用 cgdb 執行程式, 進入 gdb 後輸入:
(gdb) b gtk_init_check (gdb) b gdk_init_check (gdb) directory /my/path/to/gtk+2.0-2.24.10/ (gdb) set substitute-path /.../gtk+2.0-2.24.10/ /my/path/to/gtk+2.0-2.24.10/ (gdb) r
- directory 用來載入 Gtk+ 原始碼。debug symbol package 裡沒有含這部份。
- 編譯封裝 Gtk+ 的路徑十之八九和我放 Gtk+ 原始碼的路徑不同, 所以要用 set substitute-path 替換路徑, gdb 才知道如何顯示對應的原始碼。上面的 "..." 是執行 backtrace 時看到的路徑, 這裡簡化用 "..." 表示。
再來就在中斷點附近輸出收到的值, 看看 backtrace, 看看附近的原始碼, 獲得更多線索後就解決問題了。原來是我忘了呼叫 setenv("DISPLAY", ":0"), gdk_init_check() 發現無法產生 GdkDisplay, 所以就掛了。
沒有留言:
張貼留言