c gtk +:将文本文件加载到GtkSourceView的TextBuffer中

时间:2011-02-20 00:04:53

标签: gtk segmentation-fault fread gtksourceview

我正在使用带有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);
}

1 个答案:

答案 0 :(得分:2)

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

  

gchararray file_buffer;

只需使用char *

  

g_assert(fp!= NULL);

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

  

fseek(fp,0L,SEEK_END);   file_size = 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()。

要调试segfaults,最好的两个工具是:

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