2012-04-25 13 views
0

私はrealloc()でいくつかのメモリを割り当てようとしています。これまでのところ動作します。realloc()の後のセグメンテーションフォルト。割り当てられたメモリをポインタに割り当てることができません

// in header 
typedef struct { 
    int a; 
    char test[20]; 
} MyContent; 

typedef struct { 
    MyContent* values; 
    // simmilar to: MyContent values[] 
    // ... some other stuff 
} MyData; 

// in source 
void myFunction(MyData* dataPtr) { 
    dataPtr->values = NULL; 
    MyData* tempPtr = NULL; 

    for (int i = 1; i < 10; i++) { 
     tempPtr = (MyContent*) realloc(dataPtr->values, i * sizeof(MyContent)); 
     if (tempPtr == NULL) { 
      free(dataPtr->values); 
      break; 
     } 
     dataPtr->values = tempPtr; // Here I get the segmentation fault 
     dataPtr->values[(i-1)].a = 42; 
     // ... 
    } 
} 

私が間違ってここに何が起こっているのかを把握することはできません:私は、構造体の変数にポインタに割り当てられたメモリを割り当てる場合でも、私は、セグメンテーションフォールトを取得します。助言がありますか?ご協力いただきありがとうございます。

+2

エラーは貼り付けられていません。上記のコードは、重要な問題が1つしかありません。これは 'realloc'が' NULL'を返すケースを誤って処理します。エラーを示すコンパイル可能な完全な例を投稿できる場合は、おそらくそれを見つけることができます。それ以外の場合は、コードで 'valgrind'を実行してください。 (ところで、このCコードまたはC++コードですか?両方のタグを置くと、それは非常に混乱します。) –

+0

@DavidSchwartz、OPが投稿したコードはコンパイルされ、CまたはC++のいずれかで正常に実行されます:) – bdonlan

+0

@ bdonlan:そうです、それは彼が何を求めているのかを知ることは不可能です。例えば、私がそれをテストしようとしていたら、それをCコードかC++コードとしてテストすべきでしょうか?私が修正/変更を提案するつもりなら、それらはCまたはC++のコードでなければなりませんか? –

答えて

1

あなたのコードを編集したようです。編集したコードは正常に動作します。

#include<stdio.h> 
#include<malloc.h> 
#include<string.h> 
// in header 
typedef struct { 
    int a; 
    char test[20]; 
} MyContent; 

typedef struct { 
    MyContent* values; 
    // simmilar to: MyContent values[] 
    // ... some other stuff 
} MyData; 

// in source 
void myFunction(MyData* dataPtr) { 
    dataPtr->values = NULL; 
    MyData* tempPtr; 

    for (int i = 1; i < 10; i++) { 
     tempPtr = (MyData*) realloc(dataPtr->values, i * sizeof(MyContent)); 
     if (tempPtr == NULL) { 
      if(dataPtr->values) 
       free(dataPtr->values); 
      printf("realloc() failed\n"); 
      return ; 
     } 
     dataPtr->values = (MyContent*)tempPtr; // Here I get the segmentation fault 
     dataPtr->values[(i-1)].a = 42+i; 
     strcpy(dataPtr->values[(i-1)].test,"name"); 
    } 
} 

void PrintData(MyData* dataPtr) { 
    for (int i = 1; i < 10; i++) 
     printf("We have %s at %d\n",dataPtr->values[(i-1)].test,dataPtr->values[(i-1)].a); 
} 

main() { 
    MyData Sample; 
    myFunction(&Sample); 
    PrintData(&Sample); 
} 
+1

申し訳ありませんが、すべての回答中にコードが変更されました。私は問題を理解するのに不必要なすべてを取り除こうとしました。そうすることで、私は途方に捨ててしまったかもしれません。私は 'myFunction()'に渡された引数が、あなたのサンプルポストのために私が今考え出したerrouneosであることに気付きました。みんなありがとうございます。 – fondor

0

新しく割り当てられたメモリをチェックするための条件が間違っています。

if (tempPtr == NULL) { 
    // handle error condition or continue with original 'dataPtr->values' 
} 
else { 
    dataPtr->values = tempPtr; 
} 

realloc()は必ずしも1つのブロックを別のブロックに転送するとは限りません。同じポインタ領域にメモリを割り当てることがあります。

+1

これは間違っています。古いポインタが変更された場合は解放しないでください。 reallocはすでにあなたのためにそれを世話しました。 – bdonlan

+0

'reallocate'関数は、古いブロック自体を解放します。それを解放することはできません。 –

+0

@bdonlan、David、申し訳ありませんでした...ありがとう – iammilind

0

一見したところ、クラッシュを引き起こす可能性のある問題はありません。つまり、1対1のアドレス指定がちょっと変わっていますが、間違っているわけではありません。 realloc呼び出しが悪化するヒープやスタックの破損の結果を表示していないというコードに問題がある可能性があります。または、最適化を使用してコンパイルしている場合、デバッガはクラッシュが実際に発生している場所について混乱する可能性があります。 MyDataMyContentも混乱していますが、コードを編集している間にエラーが発生したと仮定します。

reallocが失敗した場合は、の後に行番号の後にクラッシュし、nullポインタに書き込むことになります。古いポインタを解放するだけでなく、tempPtr is NULLの場合は中止する必要があります。しかし、これもまた、あなたが指示した行と違う行にフォルトが発生します。

valgrindの下でプログラムを実行して、エラーを報告する場所を確認することをお勧めします。このようなエラーが最初に起こったのはその原因です。

+0

はい、私はMyDataとMyContentをrealloc()ステートメントで混同しました。申し訳ありませんが、私はそれを修正しました。私はまた、「混乱」を取り除き、混乱を招いた。 – fondor

関連する問題