Reputation: 39
So what I try to do is to dynamically allocate memory for a structure. The structure looks like this:
typedef struct{
char name[N];
int dimToys;
TOY toys[N];
}CITY;
I read some input from a .txt file and copy it in my structure.
Then I have a function in which I would like to reallocate memory(and do some other irrelevant stuff) but my program works only when I use this function one single time. If I try to realloc the memory multiple times, then my program crashes.
It looks something like this:
void next_city(CITY** cityList, *dimCities, otherstuff){
(*dimCities)++;
*cityList = realloc(*cityList, (*dimCities) * sizeof(CITY*));
otherstuff...
}
I tried running the debugger and it crashes at the line with realloc, when I call the function for the second time. The call of the function in the main function looks like this:
cityList = malloc(sizeof(CITY*));
for(...){
...
next_city(&cityList, &dimCities, otherstuff);
}
I've already tried using a temporary variable for the reallocation and then copy it in my original cityList
, but it doesn't work neither.
LATER EDIT:
Because a lot of people told me to update my question with some clarifications, I'll just show my code more clear, after I made some modifications from what you all told me.
void next_city(char line[], CITY **cityList, int *dimCities){
(*dimCities)++;
*cityList = realloc(*cityList, (*dimCities) * sizeof(CITY)); //UPDATE CITYLIST DIMENSION
cityList[(*dimCities) - 1]->dimToys = 0;
char *word = strtok(line, " ");
strcpy((cityList[(*dimCities) - 1]->name), word); //INSERET NAME OF THE CITY
word = strtok(NULL, " ");
strcpy((cityList[(*dimCities) - 1]->toys[cityList[(*dimCities) - 1]->dimToys].toyType), word); //INSERT NAME OF THE TOY
}
int main(){
int nrPasi;
int dimCities = 0;
scanf("%d", &nrPasi);
fgetc(stdin);
int i;
CITY *cityList;
cityList = NULL;
char line[100];
for(i = 0;i < nrPasi;i++){
fgets(line, 100, stdin);
next_city1(line, &cityList, &dimCities);
}
return 0;
}
So I basically read something like
3
Berlin car
Berlin doll
Madrid jacket
And I just want to read it step by step. After I switched CITY* with CITY now realloc doesn't break my program, but it happens on the next line, when I try to access it. I get SISGEV
Upvotes: 2
Views: 2762
Reputation: 72
Assuming you are wanting to simply reallocate an array of pointers (to CITY) then the following works when I tested it. But as someone mentioned above, perhaps you want to have an array of CITY then you would want to allocate memory for CITY as well.
#include <stdio.h>
#include <stdlib.h>
typedef struct{
char name[10];
int dimToys;
int toys[10];
} CITY;
void next_city(CITY *** cityList, int *dimCities) {
(*dimCities)++;
*cityList = realloc(*cityList, (*dimCities) * sizeof(CITY*));
}
main(){
CITY ** cityList;
int dimCities=0;
int i;
cityList = malloc(sizeof(CITY*));
printf("%p\n", (void *) cityList); // print out the address of the memory allocated
for (i = 0 ; i < 10; i++){
next_city(&cityList, &dimCities);
malloc(1); // malloc more data to force some fragmenation so that you can see that realloc does something interesting.
printf("%p\n", cityList); // print out the address of the reallocated memory
}
}
Upvotes: -1
Reputation: 25276
You reallocate sizeof(CITY*)
That should be sizeof(CITY)
, otherwise you allocate the size of a pointer.
That wouldn't be a problem if cityList
is an array of poinetrs to CITY
s, but from your code I do not see you next allocate memory for each CITY
. So citylist
is apparently an array of CITY
s.
Because you assume realloc
gave you storage for your struct, you started filling it with data. That will now overwrite the heap, causing your program to abort upon the next call to realloc
because realloc
now works on a corrupted heap.
Upvotes: 2
Reputation: 8579
You're making a common mistake of allocating space for a pointer to CITY
not the structure itself. You need to allocate sizeof(CITY)
.
But there's a couple of other points to make...
cityList = NULL;//No need allocate anything up front.
dimCities=0u; //I'll assume this is size_t.
for(...){
...
if(next_city(&cityList, &dimCities /*, otherstuff*/)){
//There was an error. What to do now?
}
}
And
int next_city(CITY** cityList, size_t *dimCities/*, otherstuff*/){
(*dimCities)++;
CITY* newList = realloc(*cityList, (*dimCities) * sizeof(CITY));
if(newList==NULL){
//out of memory..
return 1;//Error return...
}
*cityList=newList;
otherstuff...
return 0;//Good return...
}
If you pass NULL
to realloc
it acts like malloc()
.
I don't know how you propose to handle errors but if there's insufficient memory to reallocate realloc()
does nothing and returns NULL
.
Your way of allocating one object up front is fine. But personally this way is cleaner. Allocating at least one CITY
may suit you because you never need to deal with cityList==NULL
.
If this is a simple program you might just give up and exit()
at this point. I've returned a error flag (a de facto C standard) so the surrounding program can handle it.
Upvotes: 2
Reputation: 2197
In the realloc, you use sizeof(CITY*). It seems to me that you tried to get the size of the CITY struct. So your code does not do that.
The size of CITY* is the size of the pointer holding the CITY struct, which is based on your system architecture (64 or 32 bit). This way the content of CITY cannot pass between the reallocation, causing a memory buffer override and crashing the application.
If you need the size of the CITY struct just use sizeof(CITY)
Upvotes: 1