2016-04-17 12 views
0

私のプログラムでは、データベースに別の人物を追加できるようにメモリを再割り当てしようとしています。しかし、私はEXC_BAD_ACCESSエラーを受け取ったまま、新しいエントリのファーストネームを入力します。メモリを正しく再割り当てする方法は?

void addRecord (char **firstName, char **lastName, double *scores, int *numberPeople) { 
int i; 
char **newFirstName, **newLastName; 
double *newScores; 

*numberPeople += 1; // adds person to total number of people 

newFirstName = (char**) realloc(firstName,*numberPeople*sizeof(char*)); 
newLastName = (char**) realloc(lastName,*numberPeople*sizeof(char*)); 
newScores = (double*) realloc(scores,1*sizeof(double)); 

for (i = *numberPeople - 1; i < *numberPeople; i++) { 
    newFirstName[i] = (char*) realloc(firstName, MAXIMUM_DATA_LENGTH*sizeof(char)); // MAXIMUM_DATA_LENGTH = 50 
    newLastName[i] = (char*) realloc(lastName, MAXIMUM_DATA_LENGTH*sizeof(char)); 
} 


printf("Adding New Person....\n\n"); 

for (i = *numberPeople - 1; i < *numberPeople; i++) { 
    printf("First Name of new person: "); 
    scanf("%s", newFirstName[i]); // EXC_BAD_ACCESS (code=EXC_l386_GPFLT) 

    printf("Last Name of new person: "); 
    scanf("%s", newLastName[i]); 

    printf("Score of new person: "); 
    scanf("%lf", &newScores[i]); 
} 

私は私が正しくメモリを再割り当てていないよと仮定することができます。私はまだJavaから来ているCに比較的新しいので、ポインタに関する私のスキルレベルはかなり低いです。前もって感謝します。

+1

あなたのコンパイラは、(適切に設定され、標準準拠)Cコンパイラ(またはあなたをしている使用していない変換せずに(または 'のrealloc()') ')' malloc関数(の戻り値を使用して文句を言っている場合'#include 'がありません)。 – pmg

+0

@pmg私はxcodeの最新バージョンを使用しており、 'stdlib.h'ヘッダを含んでいます。だから、うん、私は何がアップしているか分からない... – David

+1

あなたはC + +コンパイラを使用しているように見えます。私は適切に設定されたCコンパイラを使用し、2つの言語を混ぜないことをお勧めします。それらの違いは、何もないはずの問題を引き起こす可能性があります。あなたのメモリ割り当ての問題はおそらく、CまたはC++コンパイラの選択とは関係ありません。 – pmg

答えて

0

一般的な点として、すべての警告を有効にしてコンパイルし(-Wall)、警告が表示されないようにしてください。第二に、アプローチを簡素化します(下記参照)。第3に、ポインタ(誤った)使用エラーを検出するにはvalgrindが必要です。

必要以上に複雑さが増しているようです。このビットで例えば

:各反復で

for (i = *numberPeople - 1; i < *numberPeople; i++) { 
    newFirstName[i] = (char*) realloc(firstName, MAXIMUM_DATA_LENGTH*sizeof(char)); // MAXIMUM_DATA_LENGTH = 50 
    newLastName[i] = (char*) realloc(lastName, MAXIMUM_DATA_LENGTH*sizeof(char)); 
} 

、あなたは、引数としてfirstNamerealloc()を呼び出しています。これにより、データはfirstNameに解放され、異なるサイズの新しいデータセットが割り当てられます。それは最初のパススルーでは(理論上は)うまくいくが、2パス目では既に解放されているものを解放するだろう。 lastNameと同じです。さらにfirstNamelastNameは、個々のエントリを指していないので、配列自身を指しているので、間違っています。配列の個々のエントリを扱うループの各パスでIEを使用すると、配列全体が解放されます。

次はなぜですかforループの繰り返し回数はi = *numberPeople - 1; i < *numberPeopleですか?それは常に1つのエントリです。

realloc()からの返品を確認してください。最初にrealloc()に電話する前に、配列が正しくmalloc()でない場合(たとえば、)どうなりますか?

もう1つの問題は、配列をchar **としてこの関数に渡すことです。しかし、配列の位置を変更します。戻ってくると、アレイの新しい場所が失われています。

あなたがここで何をしようとしているのか分かりにくいです。

  • は、最終的な要素

    forループは必要ない

  • にあなたの三つの変数を読み、配列を展開し

    • :私はあなたがはるかに簡単なアプローチを使用することを推奨します。

      ここでは簡単なリワークがあります。私はあなたが最小限の完全な検証可能な例を提供しなかったので、これをテストしていませんが、それはあなたを助けるはずです。

      // note we use char*** as these are pointers to an array of char * 
      void 
      addRecord (char ***firstName, char ***lastName, double **scores, 
            int *numberPeople) 
      { 
          // the index we will use 
          int i = *numberPeople; 
          // add one to the number of people 
          (*numberPeople)++; 
      
          // expand the arrays - you should check for NULL returns here 
          *firstName = realloc (*firstName, *numberPeople * sizeof (char *)); 
          *lastName = realloc (*lastName, *numberPeople * sizeof (char *)); 
          *scores = realloc (*scores, *numberPeople * sizeof (char *)); 
      
          // allocate memory for the new first and last name to live in 
          *firstName[i] = malloc (MAXIMUM_DATA_LENGTH * sizeof (char)); 
          *lastName[i] = malloc (MAXIMUM_DATA_LENGTH * sizeof (char)); 
      
          printf ("Adding New Person....\n\n"); 
      
          printf ("First Name of new person: "); 
          // your format string should be amended to limit the input length to MAXIMUM_DATA_LENGTH - 1 
          // and you should check for errors 
          scanf ("%s", newFirstName[i]); 
      
          printf ("Last Name of new person: "); 
          // your format string should be amended to limit the input length to MAXIMUM_DATA_LENGTH - 1 
          // and you should check for errors 
          scanf ("%s", newLastName[i]); 
      
          printf ("Score of new person: "); 
          // you should check for errors 
          scanf ("%lf", &newScores[i]); 
      } 
      
    +0

    私は 'i = * numberPeople - 1;を反復しています。私は新しい人物を追加するときに、ループが終了する直前に新しいインデックスに追加するので、私は<* numberPeople'です。 – David

    +0

    @Davidコードを複数回実行するためにループが使用されます。あなたのコードが一度だけ実行される必要がある場合(この場合、条件は 'i'の最初の値だけ保持されます)、ループを持つ点はありません。 –

    +0

    @David索引 '* numPeople-1'に1つのエントリを追加しようとしているので、ループは必要ありません。また、これらのエントリを追加するために何かrealloc()する必要はありません。何らかの形で*割り当てますが、これらの 'realloc()'は配列全体の 'firstName'と' lastName'を解放しています(本当に 'realloc() 'を使って技術的に割り当てることはできますが、 。 – abligh