Reputation: 3654
I have an assignment where I want to implement a dynamically growing array, but I seem to be having some issues with realloc(). My code works as long as I do not actually get to the realloc() part, where for some reason only some specific values are being changed to something different. Now, I would expect the rows to be completely different if I was writing/reading out of bounds, but I can't seem to pinpoint it. The problem seems to lie between lines 30-40. Here is the code:
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 }
Here is the input file I am using:
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
The expected output is the following (which I do get as long as N is high, ie. larger than actual number of lines and does NOT cause realloc() to be invoked):
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
However, if I set N = 3, I get the following:
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
I am quite at a loss as to what is happening. I've tried examining the stack and local values using gdb, but haven't had much luck yet. I am also conflicted as to why the ID is the only thing to be corrupted. Would it be necessary make a separate function which would return a pointer to the new space I get by realloc()? I wanted to keep my code as compact as possible, so I opted to try it this way first as the man page seemed to back up my assumption about the way realloc() works. Thank you.
Upvotes: 0
Views: 185
Reputation: 182847
unsigned long ID;
Okay, ID
is an unsigned long
.
fscanf(fp, "%d %[^,], %s %f", &S[i]->ID, S[i ...
Hmm, is %d
the format specifier for an unsigned long
? I don't think so.
Also, feof
doesn't predict that a future read will succeed, it only tells you what already happened. You need to check the return value of fscanf
to see if the read succeeded.
Lastly, your realloc
call allocates too much memory. You're only trying to hold pointers in S
itself.
Upvotes: 1