Reputation: 647
I have a simple function that reallocs buffer every time I want to add one char, It works till I want to realloc 24th time. Then realloc(): invalid next size appears. Here is the code:
char * addDataChunk(char * data,char c)
{
char * p;
if(data==NULL)
{
data=(char*)malloc(sizeof(char)*2);
data[0]=c;
data[1]='\0';
return data;
}
else
{
if(p = (char*)realloc(data,((strlen(data)+1)*sizeof(char))))
{
data = p;
}
else
{
printf("realloc error\n");
}
data[strlen(data)] = c;
data[strlen(data)+1] = '\0';
return data;
}
}
and error:
*** Error in `./bootstrap': realloc(): invalid next size: 0x0000000000b9f2a0 ***
Aborted (core dumped)
Upvotes: 0
Views: 4344
Reputation: 31143
The main error is most likely here:
data[strlen(data)] = c;
data[strlen(data)+1] = '\0';
You first overwrite the null terminator with the character. Then you try to get the length of the string which doesn't have the null terminator anymore, which means you will run over the memory allocated, which means undefined behaviour. Your allocation will result in whatever size. And then you continue.
The reason why it doesn't happen before is most likely because the memory allocated happens to have a null at some point and it stays within reasonable boundaries. But not forever.
The best way would be to keep track of the size and not use the expensive strlen()
every time, but if you really must/want to, store the value in a variable first.
size_t pos = strlen(data);
data[pos] = c;
data[pos+1] = '\0';
or even switch them around:
data[strlen(data)+1] = '\0';
data[strlen(data)] = c;
Also you would reallocate the exact same amount of memory since strlen()+1
is the allocated 2 bytes from the beginning (string + null terminator). It should be strlen()+2
.
Also as a style issue, sizeof(char)
is by definition 1 so you don't need to use it unless you feel it adds something to clarity.
Upvotes: 7
Reputation: 399723
Consider the first time it grows.
The original allocation is 2 characters, which is fine, it fits the first payload character and the terminator. So the length of the string is 1
, but the length of the allocation is 2
.
The first growth then computes a new size of strlen(data) + 1
, and we know that the string length is 1
so that's 2
. Then it uses three bytes at that location ... Boom!
And so on.
You really should consider a representation that gives you the string length and the allocated length, and those should be kept separate. Cut down on the strlen()
s.
Upvotes: 2