Problem bei Zeiger auf Zeiger



  • Hallo,

    anbei mein Prog das nicht läuft.
    Ich bekomme Speicherfehler wenn die Funktion das 2. mal mit realloc Speicher vergrößert.

    Mein Prog liest eine Datei aus, stellt Speicher pro Zeile für ein Struct bereit, teilt die Zeile auf das Struct auf und gibt die Anzahl der Zeilen zurück.
    Der Zeiger für den Speicher wird aber von der main an die Funktion übergeben. (auch wenn er noch nicht initialisiert ist)
    Ich habe es so gelöst damit ich den Zeiger des Struct's auch an andere noch folgende Funktionen übergeben kann.

    Ich hoffe Ihr könnt mir helfen, da diese Problem meine C-Kenntnisse überschreitet ? 😕

    typedef struct
    {
     int mpi_adr;
    char typ;
     int db_nr;
     int byte_nr;
     int datenlaenge;    
     int var_laenge;     /* in Byte */
    } block;
    
    /*#############################################################################################################*/
    int main(int argc, char *argv[])
    {
    int sst,y,x,blocknr, max_block;
    char *lesen;
    block *blockkennung;
    
    /*--------------------------------------------------------------------------------------------*/
    /* Parameter-Datei einlesen */
    
            while (1)
                  {
                  max_block = 0;
    
                  max_block = read_param(&blockkennung);
    
                  if (max_block <= 0) exit (-1);
    
    /*--------------------------------------------------------------------------------------------*/
    /* jeweiligen Block vorbereiten zum lesen */
    
                    for ( blocknr = 0 ; blocknr < max_block ; blocknr++)
                        {
                        printf ("%s", &blockkennung[blocknr].typ);
                        }
    
    usw.
    
    /*##################################################################################################################*/
    int read_param(block **blockkennung)
    {
    FILE *fp;
    char zeile[255];
    int max_block;
    
        if ((fp = fopen(parafile, "r")) == NULL)
           {
           /* ERROR */ ;
           printf ("parameter-Datei konnte zum lesen für die Schnittstelle nicht geöffnet werden");
           return -1;
           }
    
           max_block = 0;      /* zeilenzähler aus der parameterdatei */
           /* File komplett einlesen */
    
           while ( fgets(zeile, sizeof(zeile), fp) )
                 {
                 if (zeile[0] == '#' || strlen(zeile) == 0)
                    {
                     continue;
                    }
    
                 if (*blockkennung == NULL || max_block <= 0)
                    {
                     if ((*blockkennung = malloc(2 * sizeof(block))) == NULL)
                         {
                          printf ("Speicherfehler in der Funktion \"read_param\"");
                          return -1;
                         }
    
                     sscanf (zeile , "%i , %c , %i , %i , %i , %i" , blockkennung[0]->mpi_adr,
                                                                     &blockkennung[0]->typ,
                                                                     &blockkennung[0]->db_nr,
                                                                     &blockkennung[0]->byte_nr,
                                                                     &blockkennung[0]->datenlaenge,
                                                                     &blockkennung[0]->var_laenge
                                                                     );
                      max_block++;
                      }
                   else
                      {
                      if ((*blockkennung = realloc(*blockkennung , (max_block + 1) * sizeof(block))) == NULL)
                           {
                            printf ("Speicherfehler in der Funktion \"read_param\"");
                            return -1;
                           }
    
                       sscanf (zeile , "%i , %c , %i , %i , %i , %i" , &blockkennung[max_block]->mpi_adr,
                                                                       &blockkennung[max_block]->typ,
                                                                       &blockkennung[max_block]->db_nr,
                                                                       &blockkennung[max_block]->byte_nr,
                                                                       &blockkennung[max_block]->datenlaenge,
                                                                       &blockkennung[max_block]->var_laenge
                                                                       );
                        max_block++;
                        }
    
                 }
    
            fclose (fp);
    
    return max_block;
    }
    

    Danke
    worst_case



  • Hallo ....

    zunächst solltest Du mal Deinen Code etwas vereinfachen. Doppelte gleiche Codezeilen bedeuten meist immer schwerer zu verstehenden Code. Für read_param() sollte das etwa so aussehen:

    int read_param(block **blockkennung)
    {
    FILE *fp ;
    char zeile[255];
    int max_block;
    
        if ((fp = fopen("bla..", "r")) == NULL)  { /*...*/ return -1; }
    
        max_block = 0;      /* zeilenzähler aus der parameterdatei */
           /* File komplett einlesen */
    
        while ( fgets(zeile, sizeof(zeile), fp) ) {
            if (zeile[0] == '#' || strlen(zeile) == 0)  continue;
    
            if (*blockkennung == NULL) {
                puts("malloc...");
                *blockkennung = malloc(sizeof(block));
            }
            else {
                puts("realloc");
                *blockkennung = realloc(*blockkennung, (max_block+1) * sizeof(block));
            }
    
            if (*blockkennung == NULL) {
                puts("Speicherfehler...");
                return -1;
            }
    
            sscanf (zeile , "%d , %c , %d , %d , %d , %d" , &blockkennung[max_block]->mpi_adr,
                                                            &blockkennung[max_block]->typ,
                                                            &blockkennung[max_block]->db_nr,
                                                            &blockkennung[max_block]->byte_nr,
                                                            &blockkennung[max_block]->datenlaenge,
                                                            &blockkennung[max_block]->var_laenge  );
            ++max_block;
        }
    
        fclose(fp);
    
        return max_block;
    }
    

    Meine Änderungen an der Struktur sollten schnell ersichtlich sein; Für den sscanf() solltest Du '%d' statt '%i' als Formatstring wählen. Deine Strategie, Speicher zu allozieren, habe ich jetzt mal nicht verändert um das ganze übersichtlich und einfach zu halten.

    Wichtig ist IMHO noch, dass Du in main() den Zeiger 'blockkennung' initialisierst:

    block *blockkennung = NULL;
    

    Dann sollte alles wie gewünscht arbeiten.

    Letztlich gab's einen Fehler beim ersten sscanf():

    blockkennung[0]->mpi_adr
    

    sollte wohl so lauten:

    &blockkennung[0]->mpi_adr
    


  • Danke für die Antwort.

    Bin noch etwas grün bei der optischen (einfachen) Gestaltung des Codes.
    Das Prog funkt trotzdem nicht. Der 2. Schreibzugriff auf das Struct gibt einen Speicherfehler.

    Jetzt habe ich aber beim debuggen gesehen, daß der malloc einen Speicher reserviert und auch die Daten auf den Speicher ankommen (&blockkennung[max_block].. usw)
    Nach dem ersten realloc kann ich das schreiben jedoch nicht beobachten.
    Also schreibe ich irgenwo anders hin.

    Jedoch warum ?
    Ist hier irgendwo ein Fehler bei realloc, ich kann nicht's entdecken.

    Danke
    worst_case

    PS: Hat das etwas bensonderes auf sich das du puts anstatt printf benutze ?

    [ Dieser Beitrag wurde am 05.07.2003 um 13:07 Uhr von worst_case editiert. ]



  • Ups.... Sorry. Versuche mal diesen Code:

    sscanf (zeile , "%d , %c , %d , %d , %d , %d" , &((*blockkennung)[max_block].mpi_adr),
                                                            &((*blockkennung)[max_block].typ),
                                                            &((*blockkennung)[max_block].db_nr),
                                                            &((*blockkennung)[max_block].byte_nr),
                                                            &((*blockkennung)[max_block].datenlaenge),
                                                            &((*blockkennung)[max_block].var_laenge)  );
    


  • Original erstellt von worst_case:
    ...
    PS: Hat das etwas bensonderes auf sich das du puts anstatt printf benutze ?
    ...

    Naja. Warum sollte ich mit dem printf()-Monster einen Text ausgeben wollen, wenn puts() auch geht und kürzer ist..



  • Hallo,

    danke, so scheint es zu funktionieren.
    Nochmals zum Verständnis

    "&((*blockkennung)[max_block].mpi_adr)"

    bedeutet : Die Adresse des Zeigers welcher auf [max_block].mpi_adr zeigt

    oder ?

    Und noch was... wenn ich den Speicher *blockkennung in der main wieder freigenen will, wie muss ich dann vorgehen

    free(*blockkennung);

    worst_case

    [ Dieser Beitrag wurde am 05.07.2003 um 14:16 Uhr von worst_case editiert. ]



  • Original erstellt von worst_case:
    **...
    Nochmals zum Verständnis

    "&((*blockkennung)[max_block].mpi_adr)"

    bedeutet : Die Adresse des Zeigers welcher auf [max_block].mpi_adr zeigt
    ...**

    Fast. Ich geb' Dir nen Tipp: Statt

    int read_param(block **blockkennung)
    

    hätte man auch schreiben können

    int read_param(block *blockkennung[])
    

    Jetzt sollte es besser verständlich sein... Wenn nicht, frag einfach nochmal... :))


Anmelden zum Antworten