0

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

1 回答 1

2

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

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 (a char*) 而不是 &file_buffer (a char**)。这可能是立即损坏的实际原因。

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

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

看看 g_file_get_contents() 的实现,看看这里的一种方法。您还可以使用 g_file_load_contents 来使用 GFile 而不是路径(便携式,使用 vfs),或者在实际应用程序中更好的是 g_file_load_contents_async()。

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

  • 在 gdb 中运行,等待崩溃,然后键入“bt”;编译时一定要在编译器中使用 -g
  • 在 valgrind 中运行,看看它说你在哪里看坏记忆
于 2011-02-20T02:41:08.070 回答