I am getting a STATUS_ACCESS_VIOLATION at run time in this C program I am creating, and I believe this is due to initialising structs all at once, and then using malloc() to increase their size, causing pointers to reference memory already in use. This is the function where this exception occurs:
void process_track(char filename[], struct track *tracks) {
int i = 0;
FILE* fp;
int lines;
lines = count_file_lines(filename);
tracks = malloc(lines);
fp = fopen(filename, "r");
if (fp == NULL) {
printf("\n\"%s\" File not found", filename);
exit(1);
} else {
for (i = 0; i < lines; i++) {
fscanf(fp, "%d %d %d %d\n", &tracks[i].number, &tracks[i].startnode, &tracks[i].endnode, &tracks[i].minutes);
}
for (i = 0; i < lines; i++) {
printf("%d ", tracks[i].number);
printf("%d ", tracks[i].startnode);
printf("%d ", tracks[i].endnode);
printf("%d\n", tracks[i].minutes);
}
}
}
Specifically, it happens at the following line:
fscanf(fp, "%d %d %d %d\n", &tracks[i].number, &tracks[i].startnode, &tracks[i].endnode, &tracks[i].minutes);
The function is called in the following function (case 3):
void get_file(char textfilename[], int optnumber) {
struct node *nodes;
struct track *tracks;
struct course *courses;
struct entrant *entrants;
struct checkpointdata *checkpointdatas;
char filename[20]; //Array of char for filename
printf("Enter the name of the %s text file(with file extension) :", textfilename);
scanf(" %[a-zA-Z._1-9]", &filename);
switch (optnumber) {
case 1:
process_name(filename);
break;
case 2:
process_node(filename, nodes);
break;
case 3:
process_track(filename, tracks);
break;
case 4:
process_course(filename, courses);
break;
case 5:
process_entrant(filename, entrants);
break;
case 6:
process_checkpointdata(filename, checkpointdatas);
break;
}
}
It reads the first line fine, but fails after that. Since the other "process_[data]" are very similar, I tried those too. Some would work fine, some would also come up with the exception, and some would retrieve garbage on output.
How would I work around this, or allocate memory so that it does not clash with pre-allocated memory (if this indeed is the problem)?
malloc()
accepts the number of bytes to allocate, not the number of elements. The posted code is only allocating lines
bytes:
tracks = malloc(lines);
which is not enough for an array of struct track
and will result in the subsequent for
loops writing to and reading from beyond the bounds of the allocated memory block. Pass the size of the element as well as the number of elements:
tracks = malloc(lines * sizeof(*tracks));
Note that any change made to tracks
within the function is visible only to that function. As tracks
is not actually used after the call to the function the argument could be replaced with a local variable.
Remember for every malloc()
there must be a free()
.