2016-11-10 24 views
1

の配列とのrealloc私は、動的に構造体の配列をやっている製品のリストを割り当てるが、これは数回(3〜5回)に対してのみ機能し、その後、私はこのエラーを得ました。 `./test"でC - 構造体

*エラー:のrealloc():無効次のサイズ:* 0x000055bc0b44f260

ここでは、これは大学のための仕事の一部であり、私のコードです。

#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

:realloc'が失敗し、あなたが失うことになるNULLポインタを返す '場合はまずあなたは、戻ってあなたがrealloc''に渡すポインタに割り当てるべきではありません

は、これは問題を修正します元のポインタとメモリリークを持っています。そして、あなたは[ 'malloc'(や友人)のキャストについては、この議論]をお読みください(http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/605858)。 –

+0

問題としては、あなたが割り当てるメモリの境界外に書いているようです。このような問題を見つけるには、[Valgrind](http://valgrind.org/)などのツールを使用するとよいでしょう。 –

+0

'のはfopen( "products.txt"、 "W +");' - > 'FP =のfopen( "products.txt"、 "W +");私は –

答えて

1

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

tamがある場合は、1を言うが、あなたはtam * sizeof(Product)をreallocのが、今あなたが製品のためのスペースを必要とするので、あなたは、(tam + 1) * sizeof(Product)をreallocをする必要があります。物事のカップルが

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

この:

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

は、あなたが最初の引数として渡された同じ変数への直接のreallocの結果を割り当ててはならないということである済み再割り当ての最初のルールに違反します。そうしたときに失敗すると、古いポインタが失われてしまいました。

第2に、malloc(),realloc()scanf()などのさまざまな関数の戻り値をチェックしません。これもまた枢機卿の罪です。

まだ壊れたプログラム、使用valgrindのをあなたに残し、そのすべてを修正する場合。問題はここにある

+3

*注意してください、あなたは「済み再割り当ての最初のルール」についてよろしいですか? [man page](http://pubs.opengroup.org/onlinepubs/009695399/functions/realloc.html)には次のように書かれています:_メモリオブジェクトの新しいサイズがオブジェクトの移動を必要とする場合、前回のインスタンス生成のためのスペースオブジェクトは解放されます。_ –

+3

@KeineLust:はい私は確信しています。私が「失敗すれば」と言いました。あなたはそれが成功すると仮定しています。 –

+1

よろしくお願いします。 –