2016-11-10 8 views
1

Ich mache ein Array von Strukturen, um dynamisch eine Liste von Produkten zuzuordnen, aber das funktioniert nur für ein paar Mal (3 ~ 5 mal) und dann habe ich diesen Fehler.C - Realloc mit Array von Strukturen

* Fehler in `./test ': realloc(): ungültig nächste Größe: 0x000055bc0b44f260 *

Hier ist mein Code, ist dieser Teil eines Werkes für die Hochschule ist.

#include <stdio.h> 
#include <stdlib.h> 

typedef struct { 
    int cod; 
    float price; 
} Product; 

int main() { 

    FILE *fp; 

    fp = fopen("products.txt", "r+"); 

    if(fp == NULL) 
     fopen("products.txt", "w+"); 

    int control = 1; 
    int choice; 
    int tam = 0; 
    int i; 
    Product *p1; 

    p1 = malloc(sizeof(Product)); 

    while(fread(&p1[0], sizeof(Product), 1, fp) != NULL){ 
     tam++; 
    } 

    if(tam > 1){ 
     rewind(fp); 

     p1 = malloc((tam) * sizeof(*p1)); 

     for (int i = 0; i < tam; i++){ 
      fread(&p1[i], sizeof(Product), 1, fp); 
     } 
    } 

    rewind(fp); 

    do { 
     printf("1 - Add product\n2 - Show all products\n3 - Exit\n-> "); 
     scanf(" %d", &choice); 

     switch (choice) { 
      case 1: 
       if (tam == 0) { 
        //p1 = malloc(sizeof(Product)); 
        printf("Digit the product code: "); 
        scanf(" %d", &p1[tam].cod); 
        printf("Digit the product price: "); 
        scanf(" %f", &p1[tam].price); 
        tam++; 
       } else { 
        printf("***Realloqing: %d***\n", tam * sizeof(*p1)); 
        p1 = (Product*)realloc(p1, (tam) * sizeof(Product)); 
        for (i = tam; i > 0; i--) { 
         p1[i].cod = p1[i-1].cod; 
         p1[i].price = p1[i-1].price; 
        } 
        printf("Digit the product code: "); 
        scanf(" %d", &p1[0].cod); 
        printf("Digit the product price: "); 
        scanf(" %f", &p1[0].price); 
        tam++; 
       } 
      break; 
      case 2: 
       for (i = 0; i < tam; i++) { 
        printf("Product code: %d\nProduct price: %f\n", p1[i].cod, p1[i].price); 
       } 
      break; 
      case 3: 
       control = 0; 
      break; 
     } 

    } while (control); 

    for (int i = 0; i < tam; i++){ 
     fwrite(&p1[i], sizeof(Product), 1, fp); 
    } 

    fclose(fp); 

    free(p1); 

    return 0; 
} 
+1

Ein paar Dinge: Erstens sollten Sie nicht auf den Zeiger Sie 'realloc' passieren zuweisen zurück, wenn' realloc' schlägt fehl und gibt einen Null-Zeiger Sie verlieren der ursprüngliche Zeiger und ein Speicherleck haben. Dann sollten Sie [diese Diskussion über Casting 'malloc' (und Freunde) lesen (http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/605858). –

+0

Was Ihr Problem betrifft, so scheint es, dass Sie außerhalb des Speicherbereichs schreiben, den Sie zuweisen. Vielleicht möchten Sie ein Tool wie [Valgrind] (http://valgrind.org/) verwenden, um solche Probleme zu finden. –

+0

'fopen (" products.txt "," w + ");' -> 'fp = fopen (" produkte.txt "," w + ");' –

Antwort

1

Das Problem ist hier:

printf("***Realloqing: %d***\n", tam * sizeof(*p1)); 
    p1 = (Product*)realloc(p1, tam * sizeof(Product)); 

Wenn tam, sagen 1, dann realloc Sie tam * sizeof(Product), aber Sie müssen (tam + 1) * sizeof(Product), realloc denn jetzt müssen Sie Platz für Produkte.

So behebt das Problem:

printf("***Realloqing: %d***\n", (tam + 1) * sizeof(*p1)); 
    p1 = (Product*)realloc(p1, (tam + 1) * sizeof(Product)); 
1

Dieses:

p1 = (Product*)realloc(p1, (tam) * sizeof(Product)); 

Violates die erste Regel des Realloc, die, dass Sie darf nicht das Ergebnis von realloc zuweisen direkt auf die gleiche Variable, die als erstes Argument übergeben wird. Wenn Sie dies tun, haben Sie den alten Zeiger verloren (durchgesickert).

Zweitens überprüfen Sie nicht die Rückgabewerte von verschiedenen Funktionen wie malloc(), realloc() und scanf(). Auch dies ist eine Hauptsünde.

Wenn Sie alles reparieren, was Sie immer noch mit einem fehlerhaften Programm behaftet, verwenden Sie Valgrind.

+3

Bist du dir sicher über die "Erste Regel von Realloc"? Die [man page] (http://pubs.opengroup.org/onlinepubs/009695399/functions/realloc.html) sagt: _Wenn die neue Größe des Speicherobjekts eine Bewegung des Objekts erfordern würde, würde der Platz für die vorherige Instanziierung von das Objekt ist frei._ –

+3

@KeineLust: Ja bin ich mir sicher. Beachten Sie, dass ich sagte "wenn es schief geht." Sie gehen davon aus, dass es gelingt. –

+1

Ok, ich verstehe deinen Standpunkt. –