0

この関数でセグメンテーション違反が発生しています。

/**
 * Excutes the passed query and returs the the first row as an array of 
 * strings. You must free this array by calling g_strfreev()
 */
static gchar** mysql_single_row(MYSQL *mysql_handle, char* query){
    my_ulonglong num_rows=0;
    MYSQL_RES *result = NULL;
    gchar ** single_row = NULL;
    GString *q = g_string_new(query);
    MYSQL_ROW row={0};
    int query_status = mysql_real_query(mysql_handle, q->str, q->len);

    if(query_status!=0){
        g_string_free(q, TRUE);
        return NULL;
    }
    fprintf(stderr, "Storing mysql result!\n");
    result = mysql_store_result(mysql_handle);

    if(result==NULL){
            /// it was not a query that returns statemnet (e.g. INSERT, DELETE)
            g_string_free(q, TRUE);
            return NULL;
    }

    num_rows = mysql_num_rows(result);

    fprintf(stderr, "Total rows = %Ld\n", num_rows);

    if(num_rows>0){
            /// We only fetch the first row
            row = mysql_fetch_row(result);
            fprintf(stderr, "Copy single rows\n");
            single_row =  g_strdupv(row); // <------------- SIGSEGV happens here
            fprintf(stderr, "Copy single rows done\n");
    }else{
            mysql_free_result(result);
            g_string_free(q, TRUE);
            return NULL;
    }

    /// clean up
    g_string_free(q, TRUE);
    mysql_free_result(result);
    return single_row;
}

基本的に私がやりたいことは、いくつかの「SELECT」クエリを実行し、最初の行を文字列の配列として返すことです。マニュアルによるとg_strdupv、返されたものをコピーしchar **て新しいものを作成する必要があります。これを返します。後でg_strfreev、推奨される方法を使用してこれをクリーンアップします。

しかし、なぜここでセグメンテーション違反が発生するのですか。valgrindで実行しました。出力と対応するコードはここにあります

4

1 に答える 1

3

g_strdupv()で終わる C 文字列の配列をコピーしNULLます (それぞれが NUL で終わる必要があります)。C API データ構造に関する MySQL のドキュメントにMYSQL_ROWは、「フィールド値にバイナリ データが含まれている可能性がある場合」、必ずしも NUL で終了しないバイト文字列の配列であると記載されています。したがって、 aが で終わる配列または C 文字列の配列であるMYSQL_ROWという保証はありません。NULL

g_strdupv()ターミネータを探し続けNULLますが、非プロセス メモリの読み取りを試行するまでターミネータが見つからないため、segfault が発生している可能性があります。

于 2012-07-16T13:24:15.360 に答える