【问题标题】:c gtk+: loading a text file into a GtkSourceView's TextBufferc gtk+: 将文本文件加载到 GtkSourceView 的 TextBuffer 中
【发布时间】:2011-06-30 13:46:28
【问题描述】:

我正在使用带有 gtk+ 和 gtksourceview-2.0 的 C 语言编写程序。

我正在使用 GtkFileChooser 让用户选择一个文件,当他点击它时,我希望将内容加载到 GtkSourceView'TextBuffer

这是当用户双击 GtkFileChooser 上的文件时执行的函数:

void on_file_activated(GtkWidget *widget, gpointer data) {
    GFile *file;
    FILE *fp;
    gchar *path_name;
    long file_size;
    gchararray file_buffer;
    file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(widget));
    path_name=g_file_get_path(file);
    g_debug("%s is chosen\n", path_name);
    fp=fopen(path_name, "r");
    g_assert( fp != NULL);
    fseek(fp, 0L, SEEK_END);
    file_size = ftell(fp);
    rewind(fp);
    g_debug("file size: %ld\n",file_size*sizeof(gchar));
    file_buffer=calloc(file_size, sizeof(gchar));
    g_assert(file_buffer != NULL);
    fread(&file_buffer,file_size,1,fp);
    g_debug("after fread");
    //file_buffer[file_size*sizeof(gchar)]=0;
    //g_debug("after adding zero: %s",file_buffer);
    gtk_text_buffer_set_text (textbuffer, file_buffer,2);
    g_debug("after set text");
    g_object_unref(file);
}

这是我的应用程序的输出:

** (tour_de_gtk:18107): DEBUG: /home/ufk/Projects/gtk-projects/tour-de-gtk/Debug/src/examples/example_gtk_label/main.c is chosen

** (tour_de_gtk:18107): DEBUG: file size: 16

** (tour_de_gtk:18107): DEBUG: after fread 

然后我在命令 gtk_text_buffer_set_text 上遇到分段错误

如您所见,我有两个命令被注释掉。尝试 g_debug 缓冲区显然会产生分段错误,因为我没有在字符串的末尾添加零,即使我尝试在字符串的末尾添加零,我也会遇到分段错误。我可能做错了什么。

这里我试图只写缓冲区的前两个字符,但没有运气。

有什么想法吗?

更新

完成的功能:

void on_file_activated(GtkWidget *widget, gpointer data) {
GFile *file;
gchar *path_name;
long file_size;
gchar *file_buffer;
GError *error;
gboolean read_file_status;
file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(widget));
path_name=g_file_get_path(file);
g_debug("%s is chosen\n", path_name);
read_file_status=g_file_get_contents (path_name,&file_buffer,NULL, &error);

if (read_file_status == FALSE) {
    g_error("error opening file: %s\n",error && error->message ? error->message : "No Detail");
    return;
}
gtk_text_buffer_set_text (textbuffer, file_buffer,-1);
g_debug("after set text");
g_object_unref(file);
}

【问题讨论】:

    标签: gtk segmentation-fault fread gtksourceview


    【解决方案1】:

    这里有很多可能的改进,你可能已经知道很多,只是在胡闹,但我会列出几个以防万一。

    gchararray 文件缓冲区;

    只需使用 char*

    g_assert(fp != NULL);

    应该使用 assert 来解决编程错误,而不是运行时错误,所以这里 g_printerr() 或对话框会更好

    fseek(fp, 0L, SEEK_END); 文件大小 = ftell(fp); 倒带(fp);

    fstat(fileno(fp), &statbuf) 可能是更好的方法,但整个方法有点糟糕;与其获取大小,不如只读入动态增长的缓冲区。或者,如果您愿意预先分配整个缓冲区,只需使用 g_file_get_contents()。另一种方法是 g_file_query_info() (更便携并使用 vfs)

    file_buffer=calloc(file_size, sizeof(gchar));

    g_new0(char, file_size) 更好,或者 g_malloc0(file_size)。您还需要 file_size+1 为 nul 字节腾出空间。

    fread(&file_buffer,file_size,1,fp);

    这里你需要file_buffer(一个char*)而不是&file_buffer(一个char**)。这可能是立即损坏的实际原因。

    你还需要检查fread()的返回值。

    这里还缺少读入数据的 g_utf8_validate()。

    查看 g_file_get_contents() 的实现以了解此处的一种方法。您还可以使用 g_file_load_contents 来使用 GFile 而不是路径(可移植,使用 vfs),或者在实际应用中更好的是 g_file_load_contents_async()。

    要调试段错误,最好的两个工具是:

    • 在gdb中运行,等待崩溃,然后输入“bt”;编译时一定要在编译器中使用 -g
    • 在 valgrind 中运行,看看它说你在哪里看坏记忆

    【讨论】:

    • 非常感谢您提供完整的答案。我是 gtk+ 的新手,它仍然让我感到困惑,你在这里写的每一个技巧对我来说都非常重要。将测试您的 cmets 并返回给您。
    • 谢谢,我用最终功能更新了我的主要帖子。感谢您提供的所有提示。
    • 酷。你可能仍然想要 g_utf8_validate() 或者如果有人试图打开一个 latin-1 文件或其他东西,你可能会崩溃。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多