【问题标题】:Segmentation fault at GTK+ programGTK+ 程序中的分段错误
【发布时间】:2012-02-14 13:51:19
【问题描述】:

我正在尝试使用我在gtkforums.com 工作中找到的 poppler 和 cairo 制作一个简单的 GTK+ 查看器 示例。但是我遇到了分段错误(我使用 anjuta)。

当我使用调试器时,我得到了这个:

ID:1 文件:/usr/lib/i386-linux-gnu/libgdk-x11-2.0.so.0 线路:0 功能: ?? 地址:0x1d3f16(无论如何都认为这无关紧要)

调试时的终端消息:

进程的调试终端: ------------------------------------------- &"警告:GDB:设置控制终端失败:不允许操作\n"

GLib-GObject-WARNING **:无法注册现有类型 `GdkWindow'

GLib-GObject-CRITICAL **:g_object_new:断言`G_TYPE_IS_OBJECT (object_type)' 失败

这是我的代码:

#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;
}

【问题讨论】:

  • 你能通过你的调试器告诉我们发生段错误的行吗?从这段代码中,有几个地方可能会发生这种情况。
  • 确保您在构建程序时启用了调试信息,以便调试器能够正确地告诉您崩溃的位置。
  • 我似乎找不到复制所有调试器消息的方法,但错误如下:error,msg="Cannot access memory at address 0x0"

标签: c gtk segmentation-fault


【解决方案1】:

根据您的评论,它(“无法访问地址 0x0 的内存”)似乎程序有一个失败的函数,但您没有检查函数的返回值以确保它不是NULL 使用前。

纯粹基于上面的代码示例,第一种情况是如果gtk_window_new 失败;那么g_signal_connect等函数就不能合理的使用win的值了。

当我编译 sn-p 时,它编译得很好,没有警告,并且执行正确。有关于 PDF 文档的 poppler 错误消息,但与您的问题无关。

因此,您的问题可能在其他地方(不在包含的示例中)或一个小错误。

【讨论】:

  • 很奇怪它对你有用,当我尝试运行它并得到分段错误时,这是​​我的终端错误:GLib-GObject-WARNING **: cannot register existing type GdkWindow' GLib-GObject-CRITICAL **: g_object_new: assertion G_TYPE_IS_OBJECT ( object_type)' 失败
【解决方案2】:

获取更多信息的一种方法是在调试器中的 g_log 上设置断点并获取警告/严重的回溯。通过回溯,您将能够看到您的代码究竟在哪里调用了失败的 gtk+ 函数。

【讨论】:

  • 如何在 anjuta IDE 中做到这一点?
  • 不确定如何在 Anjuta 中执行此操作,但在命令行 gdb 中您会编写 'break g_log'。
猜你喜欢
  • 1970-01-01
  • 2012-05-21
  • 1970-01-01
  • 1970-01-01
  • 2018-11-18
  • 1970-01-01
  • 2018-04-25
  • 2012-10-12
相关资源
最近更新 更多