2012-02-14 90 views
1

我想用一個簡單的GTK +查看器作爲例子使用poppler和cairo,我發現它在gtkforums.com的工作。但是,我收到了分段錯誤(我使用anjuta)。GTK +程序中的分段錯誤

當我使用調試器我得到這個:

ID:1 文件:/usr/lib/i386-linux-gnu/libgdk-x11-2.0.so.0 行:0 功能:?? 地址:0x1d3f16(不要認爲反正事項)

終端消息在調試時:

Debug Terminal for the process: ------------------------------- &"warning: GDB: Failed to set controlling terminal: Operation not permitted\n"

GLib-GObject-WARNING **: cannot register existing type `GdkWindow'

GLib-GObject-CRITICAL **: g_object_new: assertion `G_TYPE_IS_OBJECT (object_type)' failed

這裏是我的代碼:

#include <config.h> 
#include <glib/gi18n.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <glib.h> 
#include <gtk/gtk.h> 
#include <gdk/gdk.h> 
#include <cairo.h> 
#include <poppler.h> 

/* gcc `pkg-config --cflags --libs gtk+-2.0 poppler-glib` -o pdfviewer pdfviewer.c */ 

static PopplerDocument* doc; 
static PopplerPage* page; 

static void 
on_destroy(GtkWidget* w, gpointer data) { 
    gtk_main_quit(); 
} 

static gboolean 
on_expose(GtkWidget* w, GdkEventExpose* e, gpointer data) { 
    cairo_t* cr; 
    cr = gdk_cairo_create(w->window); 
    poppler_page_render(page, cr); 
    cairo_destroy(cr); 
    return FALSE; 
} 

int main(int argc, char* argv[]) { 
    GtkWidget* win; 
    GError* err = NULL; 

    gtk_init(&argc, &argv); 

    doc = poppler_document_new_from_file("file:///home/user/test.pdf", NULL, &err); 
    if (!doc) { 
     printf("%s\n", err->message); 
     g_object_unref(err); 
     return 2; 
    } 

    page = poppler_document_get_page(doc, 0); 
    if(!page) { 
     printf("Could not open first page of document\n"); 
     g_object_unref(doc); 
     return 3; 
    } 

    int pages = poppler_document_get_n_pages(doc); 
    printf("There are %d pages in this pdf.\n", pages); 

    win = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
    g_signal_connect(G_OBJECT(win), "destroy",  G_CALLBACK(on_destroy), NULL); 
    g_signal_connect(G_OBJECT(win), "expose-event", G_CALLBACK(on_expose), NULL); 
    gtk_widget_set_app_paintable(win, TRUE); 
    gtk_widget_show_all(win); 

    gtk_main(); 

    g_object_unref(page); 
    g_object_unref(doc); 

    return 0; 
} 
+0

你可以通過你的調試器並告訴我們seg故障發生的地方嗎?從這些代碼中,可能會發生一些地方。 – 2012-02-14 13:55:48

+0

確保在啓用調試信息的情況下構建程序,以便調試器可以正確地告訴你它崩潰的位置。 – unwind 2012-02-14 13:56:30

+0

我似乎找不到方法來複制所有的調試器消息,但這裏的錯誤:錯誤,msg =「不能訪問內存在地址0x0」 – Rrjrjtlokrthjji 2012-02-14 14:42:43

回答

1

基於您的評論它(「無法訪問內存在地址0x0「)似乎程序有一個失敗的功能,但你沒有檢查函數的返回值,以確保它不是在使用之前NULL克它。

僅基於上面的代碼示例,第一種情況是gtk_window_new失敗;那麼g_signal_connect和其他函數不能合理地使用該值。

當我編譯代碼片段時,它編譯好沒有警告,並正確執行。有關於PDF文檔的poppler錯誤消息,但與您的問題無關。

所以你的問題可能是其他地方(不在包含的例子中)或一個微不足道的錯誤。

+0

很奇怪,它適用於你,這裏是我的終端錯誤,當我嘗試運行它並得到分段錯誤:GLib-GObject-警告**:無法註冊現有類型'GdkWindow' GLib-GObject-CRITICAL **:g_object_new:聲明'G_TYPE_IS_OBJECT(object_type)'失敗 – Rrjrjtlokrthjji 2012-02-14 15:58:46

1

得到更多信息的一種方法是在調試器中的g_log上設置一個斷點並獲得警告/關鍵的回溯。通過回溯,您將能夠看到代碼正在調用失敗的gtk +函數。

+0

我怎麼能在anjuta IDE中做到這一點? – Rrjrjtlokrthjji 2012-02-18 22:24:48

+0

不知道如何在Anjuta中做到這一點,但在命令行gdb中,您會寫'break g_log'。 – 2012-02-19 16:16:19