I'm writing a program using the C language with gtk+ and gtksourceview-2.0.
I'm using a GtkFileChooser for the user to choose a file and when he clicks on it, i want the content to be loaded to the GtkSourceView' TextBuffer
this is the function that gets executed when a user double click's a file on the 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);
}
this is the output of my application:
** (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
after then i get a segmentation fault on the command gtk_text_buffer_set_text
as you can see i have two commands that are commented out. trying to g_debug the buffer which obviously creates a segmentation fault because i didn't add a zero to the end of the string, and even when I try to add zero to the end of the string i get a segmentation fault. I probably did something wrong.
here i'm trying to write only the first two characters of the buffer but with no luck.
any ideas?
update
the finished function:
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);
}
There are a lot of improvements possible here, you may already know many and just be messing around, but I'll list several in case.
Just use char*
Should use assert for programming errors, not runtime errors, so here g_printerr() or a dialog would be better
fstat(fileno(fp), &statbuf) is probably a better way to do this, but the whole approach is kind of bad; rather than get the size, it's better to just read into a dynamically-growing buffer. Or if you're willing to preallocate the whole buffer, just use g_file_get_contents(). Another approach is g_file_query_info() (which is more portable and uses the vfs)
g_new0(char, file_size) is nicer, or g_malloc0(file_size). Also you need file_size+1 to make room for the nul byte.
Here you want file_buffer (a char*) rather than &file_buffer (a char**). This is probably the actual cause of the immediate breakage.
You also need to check the return value of fread().
Also missing here is g_utf8_validate() on the data read in.
Have a look at the implementation of g_file_get_contents() to see one approach here. You could also use g_file_load_contents to use a GFile instead of a path (portable, uses vfs) or better yet in a real-world app, g_file_load_contents_async().
To debug segfaults, the two best tools are: