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 でセグメンテーション違反が発生します

ご覧のとおり、コメント アウトされた 2 つのコマンドがあります。文字列の末尾にゼロを追加しなかったため、明らかにセグメンテーション違反を引き起こすバッファを g_debug しようとしました。文字列の末尾にゼロを追加しようとしても、セグメンテーション違反が発生します。私はおそらく何か間違ったことをしました。

ここでは、バッファの最初の 2 文字だけを書き込もうとしていますが、うまくいきません。

何か案は?

アップデート

完成した関数:

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 file_buffer;

char*を使用するだけです

g_assert(fp!= NULL);

実行時エラーではなくプログラミングエラーにassertを使用する必要があるため、ここではg_printerr()またはダイアログの方が適しています

fseek(fp、0L、SEEK_END); file_size = ftell(fp); rewind(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)です。また、nulバイト用のスペースを確保するためにfile_size+1が必要です。

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

ここでは、&file_buffer(char **)ではなくfile_buffer(char *)が必要です。これはおそらく、即時の破損の実際の原因です。

また、fread()の戻り値を確認する必要があります。

また、ここで欠落しているのは、読み込まれたデータのg_utf8_validate()です。

g_file_get_contents()の実装を見て、ここで1つのアプローチを確認してください。また、g_file_load_contentsを使用して、パスの代わりにGFileを使用することもできます(ポータブル、vfsを使用)。実際のアプリでは、g_file_load_contents_async()を使用することもできます。

segfaultをデバッグするための、2つの最良のツールは次のとおりです。

  • gdbで実行し、クラッシュを待ってから、「bt」と入力します。コンパイルするときは、必ずコンパイラで-gを使用してください
  • valgrindで実行し、悪いメモリを見ていると表示されている場所を確認します
于 2011-02-20T02:41:08.070 に答える