0

構造体へのポインターを埋める関数があります。これを GTK コールバックで埋めるときは、グローバル ポインターを使用して、現在使用している "nivel" に他の関数からアクセスできるようにします。記憶に問題があるのではないかと心配しています。

ポイントは、メモリが「いっぱい」になっていることです。しかし、関数を呼び出して構造体を作成する関数からプログラムが抜けるとすぐに、いくつかの結果のいずれかが得られます。

1 - エラー: glibc が破損した二重リンク リストを検出しました

2 - エラー: glibc が検出されました

3 - セグメンテーション違反。

4 - エラーはまったくありません。

エラーは実行ごとに変化するため、メモリに関するものであることがわかります。おそらく、構造体のスコープを正しく処理していませんが、解決策が見つかりません。ただし、構造体が正しく作成されていると確信しています。どんな助けでも大歓迎です。コードは次のとおりです。スペイン語の部分がいくつかありますが、重要な部分にコメントを付けました。助けてくれてありがとう!

//Struct, consists of a 2d array and size info.
struct nivel { 
    size_t filas;
    size_t columnas;
    int **mapa;
};

//Global current level pointer, I fill it with a call to the function within another function.

struct nivel *nivel_actual;

//Function to fill a struct, receives a pointer and the text file path.

    void    nuevo_nivel_desde_archivo(struct nivel * nuevo_nivel, char *nombre_archivo ){
    g_print("Leyendo archivo...\n");
    nuevo_nivel->filas = 0;
    nuevo_nivel->columnas = 0;
    int *caracter;
    int leyo_columnas = 0;
    g_print("Leyendo archivo...\n");
    g_print("Obteniendo columnas...\n");
    FILE *archivo = fopen(nombre_archivo, "r");
    while ( (caracter = fgetc(archivo)) != EOF )  {
         if ( (!(leyo_columnas)) )
            nuevo_nivel->columnas++;
         if ((caracter == '\n') & (!(leyo_columnas)))
            leyo_columnas = 1;
         else if ((caracter == '\n'))
            nuevo_nivel->filas++;
    }
    nuevo_nivel->filas++;
    nuevo_nivel->columnas--;
    g_print("Columnas %d , Filas %d\n", nuevo_nivel->columnas, nuevo_nivel->filas);
    fclose(archivo);

    int x;

    nuevo_nivel->mapa = malloc( sizeof( int ) * nuevo_nivel->filas );

    for( x = 0; x < nuevo_nivel->filas; x++ )
        nuevo_nivel->mapa[x] = malloc( sizeof( int ) * nuevo_nivel->columnas );

    //parsear caracteres dentro del archivo
    int i=0,j=0;
    archivo = fopen(nombre_archivo, "r");
    while((caracter = fgetc(archivo)) != EOF) { //encontrar numero de filas
        g_print("%c",caracter);
        switch ((int)caracter){
            case '\n': i++; j=0; break;
            case ' ':nuevo_nivel->mapa[i][j]=0; j++;break;
            case '*':nuevo_nivel->mapa[i][j]=1; j++;break;
            case '+':nuevo_nivel->mapa[i][j]=2; j++;break;
            case 'A':nuevo_nivel->mapa[i][j]=3; j++;break;
            case 'R':nuevo_nivel->mapa[i][j]=4; j++;break;
            case 'S':nuevo_nivel->mapa[i][j]=5; j++;break;
    }
    }

    fclose(archivo);
}

//Within this function is the call to the struct maker function.

static void abrir_archivo( GtkWidget *ventana1, gpointer datos){ 
 GtkWidget *ventana_sel;
 GtkWidget *ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 ventana_sel = gtk_file_chooser_dialog_new ("Seleccionar Archivo de Nivel",
                      GTK_WINDOW(ventana),
                      GTK_FILE_CHOOSER_ACTION_OPEN,
                      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                      NULL);
 if (gtk_dialog_run (GTK_DIALOG (ventana_sel)) == GTK_RESPONSE_ACCEPT)
   {
     char *nombre_archivo;

     nombre_archivo = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (ventana_sel));
     g_print(nombre_archivo);

//Here is the call

     nivel_actual = malloc (sizeof (struct nivel));
     nuevo_nivel_desde_archivo(nivel_actual,nombre_archivo);
     g_print("Archivo parseado...\n");
   }
 gtk_widget_destroy (ventana_sel);
}
4

1 に答える 1

1

nuevo_nivel->mapaは配列の配列であるため、多数のポインターを割り当てる必要がありますint

nuevo_nivel->mapa = malloc(sizeof(int*) * nuevo_nivel->filas);

sizeof(int) < sizeof(int*)お使いのプラットフォームでは、割り当てたメモリの末尾を超えて書き込みを行うことになります。

于 2013-05-02T17:46:37.460 に答える