動的に成長する配列を実装したいという割り当てがありますが、realloc()でいくつかの問題が発生しているようです。私のコードは、実際にrealloc()の部分に到達しない限り機能します。この部分では、何らかの理由で、特定の値のみが別の値に変更されています。さて、範囲外で書き込み/読み取りを行っている場合、行は完全に異なると予想されますが、それを正確に特定することはできないようです。問題は30〜40行目にあるようです。コードは次のとおりです。
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 typedef struct __student {
6 unsigned long ID;
7 char fname[33];
8 char lname[33];
9 float grade;
10 } student;
11
12 void partA(FILE *fp) {
13
14 int i, r;
15 i = r = 0;
16 int N = 1000;
17 student **S;
18
19 S = malloc(sizeof(student *) * N);
20
21 // While EOF has not been reached
22 while(!feof(fp)){
23 // Allocate enough memory to hold each student struct
24 S[i] = malloc(sizeof(student));
25 // Get each line and, using a scanset, get corresponding
26 // data into respective struct fields
27 fscanf(fp, "%d %[^,], %s %f", &S[i]->ID, S[i]->lname, S[i]->fname, &S[i]->grade );
28 i++; // Get next line into a new struct
29
30 // If array size has been reached...
31 if(i == N){
32 N *= 2;
33 // Double it
34 S = realloc(S, sizeof(student) * N);
35 if(S == NULL) {
36 // realloc has failed
37 printf("Memory reallocation failed; Fatal error.");
38 break;
39 }
40 }
41 }
42 r = i-1;
43 // Output data
44 printf("Name\t\t\t\t\t\t\t\t [ID]\t\t:\tGrade\n");
45 printf("___________________________________________________________________________________________________\n");
46 for(i=0; i<r; i++){
47 printf("%-32s %-32s [%lu]\t:\t%.3f\n", S[i]->fname, S[i]->lname, S[i]->ID, S[i]->grade);
48 free(S[i]);
49 }
50 }
これが私が使用している入力ファイルです:
58205720 Broke, Jim 95
29571057 Crowe, John 88
12957206 Moore, Kim 22
59376027 Sarasvaki, Joe 79
49027650 Morrigan, Tracy 68
30773967 Trund, Geoffrey 99
34850470 Perry, Tracey 77
70209658 Oatnel, Skye 89
期待される出力は次のとおりです(Nが高い限り、つまり実際の行数よりも多く、realloc()が呼び出されない限り取得します)。
Name [ID] : Grade
___________________________________________________________________________________________________
Jim Broke [58205720] : 95.000
John Crowe [29571057] : 88.000
Kim Moore [12957206] : 22.000
Joe Sarasvaki [59376027] : 79.000
Tracy Morrigan [49027650] : 68.000
Geoffrey Trund [30773967] : 99.000
Tracey Perry [34850470] : 77.000
Skye Oatnel [70209658] : 89.000
ただし、N = 3に設定すると、次のようになります。
Name [ID] : Grade
___________________________________________________________________________________________________
Jim Broke [58205720] : 95.000
John Crowe [29571057] : 88.000
Kim Moore [12957206] : 22.000
Joe Sarasvaki [59376027] : 79.000
Tracy Morrigan [49027650] : 68.000
Geoffrey Trund [30773967] : 99.000
Tracey Perry [231963084454] : 77.000
Skye Oatnel [231998443642] : 89.000
私は何が起こっているのかについてかなり途方に暮れています。gdbを使用してスタックとローカルの値を調べてみましたが、まだあまりうまくいきませんでした。また、IDが破損する唯一のものである理由についても矛盾しています。realloc()によって取得した新しいスペースへのポインターを返す別の関数を作成する必要がありますか?コードをできるだけコンパクトに保ちたいと思ったので、manページがrealloc()の動作方法に関する私の仮定を裏付けているように見えたので、最初にこの方法で試すことにしました。ありがとうございました。