473,324 Members | 2,268 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,324 software developers and data experts.

realloc(): invalid next size

Greetings all,

I have a program that used the realloc() function to change the
allocated size of a buffer, the program works with some arguments, but
with some other arguments, it will show me the error message like:

*** glibc detected *** realloc(): invalid next size: 0x0804c3a8 ***

and then I inserted a perror("realloc") to see what happend, it says that:

realloc: Illegal seek
the realloc() is in a loop:

for (m = 0; m < len; m++) {
if (isspace(data[m]) || ispunct(data[m]) ||
isdigit(data[m]))
printf("%c", data[m]);
else {
p = min(strcspn(&data[m], " "),
strcspn(&data[m], "\t"),
strcspn(&data[m], "\r"),
strcspn(&data[m], "\n"));
key = realloc(key, p);
strncpy(key, &data[m], p);
key[p] = '\0';
trans(key, p);
m = m + p - 1;
}
}

and the "key" is already malloced before the loop:

char *key = malloc(1);

Any suggestion could be helpful, thx very much!

Deephay
Apr 11 '06 #1
27 31219
Deephay <tu*****@gmail.com> wrote:
I have a program that used the realloc() function to change the
allocated size of a buffer, the program works with some arguments, but
with some other arguments, it will show me the error message like:

*** glibc detected *** realloc(): invalid next size: 0x0804c3a8 ***

and then I inserted a perror("realloc") to see what happend, it says that:

realloc: Illegal seek
the realloc() is in a loop:

for (m = 0; m < len; m++) {
if (isspace(data[m]) || ispunct(data[m]) ||
isdigit(data[m]))
printf("%c", data[m]);
else {
p = min(strcspn(&data[m], " "),
strcspn(&data[m], "\t"),
strcspn(&data[m], "\r"),
strcspn(&data[m], "\n"));
Why not simply use strcspn(&data[m], " \t\r\n")?
key = realloc(key, p);
strncpy(key, &data[m], p);
key[p] = '\0';
trans(key, p);
m = m + p - 1;
}
}

and the "key" is already malloced before the loop:

char *key = malloc(1);


Hard to say what the real problem is without any object or function
definitions, but two questions spring to mind:
- does this occur immediately, or after a few iterations;
- what actually is the value of p (and if this code isn't complete, of
key) at the point where it produces the error?

Richard
Apr 11 '06 #2
Richard Bos wrote:
Deephay <tu*****@gmail.com> wrote:
I have a program that used the realloc() function to change the
allocated size of a buffer, the program works with some arguments, but
with some other arguments, it will show me the error message like:

*** glibc detected *** realloc(): invalid next size: 0x0804c3a8 ***

and then I inserted a perror("realloc") to see what happend, it says that:

realloc: Illegal seek
the realloc() is in a loop:

for (m = 0; m < len; m++) {
if (isspace(data[m]) || ispunct(data[m]) ||
isdigit(data[m]))
printf("%c", data[m]);
else {
p = min(strcspn(&data[m], " "),
strcspn(&data[m], "\t"),
strcspn(&data[m], "\r"),
strcspn(&data[m], "\n"));
Why not simply use strcspn(&data[m], " \t\r\n")?

I have to get the index where the first "space" locates.
key = realloc(key, p);
strncpy(key, &data[m], p);
key[p] = '\0';
trans(key, p);
m = m + p - 1;
}
}

and the "key" is already malloced before the loop:

char *key = malloc(1);
Hard to say what the real problem is without any object or function
definitions, but two questions spring to mind:
- does this occur immediately, or after a few iterations;
- what actually is the value of p (and if this code isn't complete, of
key) at the point where it produces the error?

the error occurred after a few iterations, the first realloc will always
success.
the p is always larger than 0, I have tested. Actually it will be a
quite normal
value where the error produced, say, 7, 8, or whatever...

What I think now is that it might be a bug of glibc...
I searched with google and found some unsolved problem like the one I have.

What I did now is, declare a key[50] static, this works fine.
I still want to make sure what the problem is, though.
Richard


Thanks!

Deephay
Apr 11 '06 #3
Deephay wrote:
Richard Bos wrote:
Deephay <tu*****@gmail.com> wrote:
I have a program that used the realloc() function to
change the
allocated size of a buffer, the program works with some
arguments, but with some other arguments, it will show me
the error message like:

*** glibc detected *** realloc(): invalid next size:
0x0804c3a8 ***
Why not simply use strcspn(&data[m], " \t\r\n")?

I have to get the index where the first "space" locates.


Ok, that would be "strcspn(&data[m], " \t\r\n")+1" if there are
any spaces, but you did not add 1 in your code either.
key = realloc(key, p);
strncpy(key, &data[m], p);
key[p] = '\0';

I still want to make sure what the problem is, though.


The last assignment above invokes undefined behavior even if
realloc() did not return NULL.

Ralf
Apr 11 '06 #4

In article <e1***********@news3.infoave.net>, Deephay <tu*****@gmail.com> writes:

I have a program that used the realloc() function to change the
allocated size of a buffer, the program works with some arguments, but
with some other arguments, it will show me the error message like:

*** glibc detected *** realloc(): invalid next size: 0x0804c3a8 ***
glibc is off-topic for comp.lang.c, but this is glibc telling you
that you have invoked Undefined Behavior. Probably you have
corrupted glibc's housekeeping data by performing an illegal
operation on an object with dynamic storage duration, such as writing
past the end of an allocated area.
and then I inserted a perror("realloc") to see what happend, it says that:
What will happen is that you will get a meaningless message written
to stderr. realloc does not set errno, so perror will report whatever
happens to have already been in errno.
the realloc() is in a loop:

for (m = 0; m < len; m++) {
if (isspace(data[m]) || ispunct(data[m]) ||
isdigit(data[m]))
printf("%c", data[m]);
else {
p = min(strcspn(&data[m], " "),
strcspn(&data[m], "\t"),
strcspn(&data[m], "\r"),
strcspn(&data[m], "\n"));
key = realloc(key, p);
Wrong for two reasons. You failed to check whether realloc
succeeded, and if it failed, you just lost the old value of "key"
and so introduced a memory leak.

The result of realloc should always be stored in a temporary
variable and should be checked for null. If it is null, remember
to free the old value:

char *newkey;
newkey = realloc(key, p);
if (! newkey)
{
free(key);
[perform error handling]
}
key = newkey;
strncpy(key, &data[m], p);
key[p] = '\0';
You just wrote past the end of the allocated area. Since key is an
area of p bytes, valid indices are 0 through p-1, inclusive.
and the "key" is already malloced before the loop:

char *key = malloc(1);
Did you check to see whether malloc succeeded?
Any suggestion could be helpful, thx very much!


Read the comp.lang.c FAQ (http://www.c-faq.com is one source). Get a
copy of the C standard. C makes little effort to protect you from
yourself; you will only produce reliable, correct C code by learning
the language and its pitfalls.

--
Michael Wojcik mi************@microfocus.com

The lecturer was detailing a proof on the blackboard. He started to say,
"From the above it is obvious that ...". Then he stepped back and thought
deeply for a while. Then he left the room. We waited. Five minutes
later he returned smiling and said, "Yes, it is obvious", and continued
to outline the proof. -- John O'Gorman
Apr 11 '06 #5
Deephay <tu*****@gmail.com> wrote:
Richard Bos wrote:
Deephay <tu*****@gmail.com> wrote:
p = min(strcspn(&data[m], " "),
strcspn(&data[m], "\t"),
strcspn(&data[m], "\r"),
strcspn(&data[m], "\n"));
Why not simply use strcspn(&data[m], " \t\r\n")?

I have to get the index where the first "space" locates.


That one call does the same thing as those four calls plus a properly
written min() function.
key = realloc(key, p);
strncpy(key, &data[m], p);
key[p] = '\0';
trans(key, p);
m = m + p - 1; and the "key" is already malloced before the loop:

char *key = malloc(1);


Hard to say what the real problem is without any object or function
definitions, but two questions spring to mind:
- does this occur immediately, or after a few iterations;
- what actually is the value of p (and if this code isn't complete, of
key) at the point where it produces the error?

the error occurred after a few iterations, the first realloc will always
success.
the p is always larger than 0, I have tested. Actually it will be a
quite normal value where the error produced, say, 7, 8, or whatever...

What I think now is that it might be a bug of glibc...


That is the last thing I would consider.
I searched with google and found some unsolved problem like the one I have.
You can find a great many confused bug-writers on the 'web, yes, many of
them blaming their tools for their own mistakes.
What I did now is, declare a key[50] static, this works fine.
It probably works around a bug - using strncpy() without thorough
understanding is asking for one, btw - and leaves a time bomb in your
code. What happens if you encounter a token larger than 50 characters?
Worse, what if you encounter one of _precisely_ 50 characters?
I still want to make sure what the problem is, though.


Without more code which demonstrates the problem precisely, it is
impossible to be certain. If the above is your exact code, you have
several off-by-one errors; then again, if the above is your exact code,
it doesn't compile, because there is a lot missing.

If you want more help, what you should do now is the following:
- make a copy of your existing code;
- whittle it down to the smallest _compilable_ program which still
exhibits the same problem;
- post _exactly_ that code. Paste, do not retype it into your post,
otherwise you'll make typos.

Richard
Apr 11 '06 #6
Michael Wojcik wrote:
The result of realloc should always be stored in a temporary
variable and should be checked for null. If it is null, remember
to free the old value:

char *newkey;
newkey = realloc(key, p);
if (! newkey)
{
free(key);
[perform error handling]
}
key = newkey;


Uh? Doesn't realloc(), when it doesn't fail, call free() all by itself
if there's a need for that? Also suppose the reallocated memory doesn't
'move' (newkey == key); doing a "free(key);" now could be disastrous.

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Apr 11 '06 #7
>Michael Wojcik wrote:
The result of realloc should always be stored in a temporary
variable and should be checked for null. If it is null, remember
to free the old value ...

In article <sl*******************@ID-203069.user.individual.net>
Pedro Graca <he****@hotpop.com> wrote:Uh? Doesn't realloc(), when it doesn't fail, call free() all by itself
if there's a need for that?
No!

With a few exceptions (noted below), realloc() is essentially an
optimized version of the following:

void *realloc(void *old, size_t newsize) {
size_t oldsize = __some_sort_of_magic_done_here(old);
void *new;

new = malloc(newsize);
if (new != NULL) {
memcpy(new, old, oldsize < newsize ? oldsize : newsize);
free(old);
}
return new;
}

(where the "magic" function obtains the size previously malloc()ed,
or the size of the previously malloc()ed region, whichever is
larger, based on "old", or returns 0 if old==NULL).

Note specifically that "old" is *not*, I repeat NOT, free()d if
"new" memory is not obtainable.
Also suppose the reallocated memory doesn't 'move' (newkey == key);


In this case, the return value from realloc() is necessarily not
NULL (well, except if old==NULL).

In both C89 and C99, realloc(p, 0) (where p!=NULL) is equivalent
to free(p). In at least C89 (and perhaps both C89 and C99),
realloc(NULL, 0) does something no one can quite explain. :-)
(Seriously: C89 specifically said that realloc(NULL,n) was equivalent
to malloc(n), and malloc(0) *could* be equivalent to malloc(1); it
then also said that realloc(p,0) was equivalent to free(p); so what
then is realloc(NULL,0) -- is it like malloc(0) and hence like
malloc(1), or is it just free(NULL)?)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Apr 11 '06 #8
Pedro Graca schrieb:
Michael Wojcik wrote:
The result of realloc should always be stored in a temporary
variable and should be checked for null. If it is null, remember
to free the old value:

char *newkey;
newkey = realloc(key, p);
if (! newkey)
{
free(key);
[perform error handling]
}
key = newkey;


Uh? Doesn't realloc(), when it doesn't fail, call free() all by itself
if there's a need for that? Also suppose the reallocated memory doesn't
'move' (newkey == key); doing a "free(key);" now could be disastrous.


realloc() returns a null-pointer when it fails, hence the if branch is
only taken after a failure in realloc().
Apr 11 '06 #9
Marc Thrun wrote:
Pedro Graca schrieb:
Michael Wojcik wrote:
The result of realloc should always be stored in a temporary
variable and should be checked for null. If it is null, remember
to free the old value:

char *newkey;
newkey = realloc(key, p);
if (! newkey)
{
free(key);
[perform error handling]
}
key = newkey;


Uh? Doesn't realloc(), when it doesn't fail, call free() all by itself
if there's a need for that? Also suppose the reallocated memory doesn't
'move' (newkey == key); doing a "free(key);" now could be disastrous.


realloc() returns a null-pointer when it fails, hence the if branch is
only taken after a failure in realloc().


Ah! Of course. Thank you.
(sorry Michael)
--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Apr 11 '06 #10
Chris Torek wrote:
Michael Wojcik wrote:
The result of realloc should always be stored in a temporary
variable and should be checked for null. If it is null, remember
to free the old value ...


In article <sl*******************@ID-203069.user.individual.net>
Pedro Graca <he****@hotpop.com> wrote:
Uh? Doesn't realloc(), when it doesn't fail, call free() all by itself
if there's a need for that?


No!

[snip comprehensive answer]

Thank you very much for the comprehensive answer.

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Apr 11 '06 #11

"Chris Torek" <no****@torek.net> wrote in message
news:e1********@news2.newsguy.com...
Michael Wojcik wrote:
The result of realloc should always be stored in a temporary
variable and should be checked for null. If it is null, remember
to free the old value ...

In article <sl*******************@ID-203069.user.individual.net>
Pedro Graca <he****@hotpop.com> wrote:
Uh? Doesn't realloc(), when it doesn't fail, call free() all by itself
if there's a need for that?


No!

With a few exceptions (noted below), realloc() is essentially an
optimized version of the following:

void *realloc(void *old, size_t newsize) {
size_t oldsize = __some_sort_of_magic_done_here(old);
void *new;

new = malloc(newsize);
if (new != NULL) {
memcpy(new, old, oldsize < newsize ? oldsize : newsize);
free(old);
}
return new;
}


Hmm, no NULL check for old?

<snip> (Seriously: C89 specifically said that realloc(NULL,n) was equivalent
to malloc(n), and malloc(0) *could* be equivalent to malloc(1); it
then also said that realloc(p,0) was equivalent to free(p); so what
then is realloc(NULL,0) -- is it like malloc(0) and hence like
malloc(1), or is it just free(NULL)?)


If your question wasn't rhetorical, this realloc probably answers your
question. It has undefined behavior since it doesn't determine the 'magic
mystery size' of s1...

void *my_realloc (void *s1, size_t size)
{
void *s2=NULL;

if (size!=0||s1==NULL)
s2 = malloc(size);
else
free(s1);
if (s1!=NULL)
memcpy(s2, s1, size);
return(s2);
}
Rod Pemberton
Apr 12 '06 #12

Michael Wojcik wrote:
In article <e1***********@news3.infoave.net>, Deephay <tu*****@gmail.com> writes:

I have a program that used the realloc() function to change the
allocated size of a buffer, the program works with some arguments, but
with some other arguments, it will show me the error message like:

*** glibc detected *** realloc(): invalid next size: 0x0804c3a8 ***
glibc is off-topic for comp.lang.c, but this is glibc telling you
that you have invoked Undefined Behavior. Probably you have
corrupted glibc's housekeeping data by performing an illegal
operation on an object with dynamic storage duration, such as writing
past the end of an allocated area.
and then I inserted a perror("realloc") to see what happend, it says that:


What will happen is that you will get a meaningless message written
to stderr. realloc does not set errno, so perror will report whatever
happens to have already been in errno.
the realloc() is in a loop:

for (m = 0; m < len; m++) {
if (isspace(data[m]) || ispunct(data[m]) ||
isdigit(data[m]))
printf("%c", data[m]);
else {
p = min(strcspn(&data[m], " "),
strcspn(&data[m], "\t"),
strcspn(&data[m], "\r"),
strcspn(&data[m], "\n"));
key = realloc(key, p);


Wrong for two reasons. You failed to check whether realloc
succeeded, and if it failed, you just lost the old value of "key"
and so introduced a memory leak.

The result of realloc should always be stored in a temporary
variable and should be checked for null. If it is null, remember
to free the old value:

char *newkey;
newkey = realloc(key, p);
if (! newkey)
{
free(key);
[perform error handling]
}
key = newkey;
strncpy(key, &data[m], p);
key[p] = '\0';


You just wrote past the end of the allocated area. Since key is an
area of p bytes, valid indices are 0 through p-1, inclusive.
and the "key" is already malloced before the loop:

char *key = malloc(1);


Did you check to see whether malloc succeeded?
Any suggestion could be helpful, thx very much!


Read the comp.lang.c FAQ (http://www.c-faq.com is one source). Get a
copy of the C standard. C makes little effort to protect you from
yourself; you will only produce reliable, correct C code by learning
the language and its pitfalls.


thx a lot for those suggestions!

--
Michael Wojcik mi************@microfocus.com

The lecturer was detailing a proof on the blackboard. He started to say,
"From the above it is obvious that ...". Then he stepped back and thought
deeply for a while. Then he left the room. We waited. Five minutes
later he returned smiling and said, "Yes, it is obvious", and continued
to outline the proof. -- John O'Gorman


Apr 12 '06 #13

Richard Bos wrote:
Deephay <tu*****@gmail.com> wrote:
Richard Bos wrote:
Deephay <tu*****@gmail.com> wrote: p = min(strcspn(&data[m], " "),
> strcspn(&data[m], "\t"),
> strcspn(&data[m], "\r"),
> strcspn(&data[m], "\n"));

Why not simply use strcspn(&data[m], " \t\r\n")?

I have to get the index where the first "space" locates.


That one call does the same thing as those four calls plus a properly
written min() function.
> key = realloc(key, p);
> strncpy(key, &data[m], p);
> key[p] = '\0';
> trans(key, p);
> m = m + p - 1; and the "key" is already malloced before the loop:
>
> char *key = malloc(1);

Hard to say what the real problem is without any object or function
definitions, but two questions spring to mind:
- does this occur immediately, or after a few iterations;
- what actually is the value of p (and if this code isn't complete, of
key) at the point where it produces the error?

the error occurred after a few iterations, the first realloc will always
success.
the p is always larger than 0, I have tested. Actually it will be a
quite normal value where the error produced, say, 7, 8, or whatever...

What I think now is that it might be a bug of glibc...


That is the last thing I would consider.
I searched with google and found some unsolved problem like the one I have.


You can find a great many confused bug-writers on the 'web, yes, many of
them blaming their tools for their own mistakes.
What I did now is, declare a key[50] static, this works fine.


It probably works around a bug - using strncpy() without thorough
understanding is asking for one, btw - and leaves a time bomb in your
code. What happens if you encounter a token larger than 50 characters?
Worse, what if you encounter one of _precisely_ 50 characters?
I still want to make sure what the problem is, though.


Without more code which demonstrates the problem precisely, it is
impossible to be certain. If the above is your exact code, you have
several off-by-one errors; then again, if the above is your exact code,
it doesn't compile, because there is a lot missing.

If you want more help, what you should do now is the following:
- make a copy of your existing code;
- whittle it down to the smallest _compilable_ program which still
exhibits the same problem;
- post _exactly_ that code. Paste, do not retype it into your post,
otherwise you'll make typos.

Richard


thx for the suggestions, Richard, I'll try to exam the code again.

Apr 12 '06 #14
Rod Pemberton wrote:
"Chris Torek" <no****@torek.net> wrote in message
news:e1********@news2.newsguy.com...
(Seriously: C89 specifically said that realloc(NULL,n) was equivalent
to malloc(n), and malloc(0) *could* be equivalent to malloc(1); it
then also said that realloc(p,0) was equivalent to free(p); so what
then is realloc(NULL,0) -- is it like malloc(0) and hence like
malloc(1), or is it just free(NULL)?)


If your question wasn't rhetorical, this realloc probably answers your
question. It has undefined behavior since it doesn't determine the 'magic
mystery size' of s1...

void *my_realloc (void *s1, size_t size)
{
void *s2=NULL;

if (size!=0||s1==NULL)
s2 = malloc(size);
else
free(s1);
if (s1!=NULL)
memcpy(s2, s1, size);
return(s2);
}


Hmm, there seems to be something wrong with this my_realloc():

new_pointer = my_realloc(NULL, 100); /* ok */
new_pointer = my_realloc(NULL, 0); /* ok */
new_pointer = my_realloc(old_pointer, 100); /* old_pointer not free'd */
new_pointer = my_realloc(old_pointer, 0); /* memcpy(NULL, ????, 0); */

In the last example, will the call to memcpy() invoke UB? Or, because
size is 0 (zero), it doesn't matter what the pointers point to?

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Apr 12 '06 #15

In article <sl*******************@ID-203069.user.individual.net>, Pedro Graca <he****@dodgeit.com> writes:
Michael Wojcik wrote:
The result of realloc should always be stored in a temporary
variable and should be checked for null. If it is null, remember
to free the old value:

char *newkey;
newkey = realloc(key, p);
if (! newkey)
{
free(key);
[perform error handling]
}
key = newkey;


Uh? Doesn't realloc(), when it doesn't fail, call free() all by itself
if there's a need for that? Also suppose the reallocated memory doesn't
'move' (newkey == key); doing a "free(key);" now could be disastrous.


The code above only frees key if realloc failed.

--
Michael Wojcik mi************@microfocus.com
Apr 12 '06 #16

"Pedro Graca" <he****@dodgeit.com> wrote in message
news:sl*******************@ID-203069.user.individual.net...
Rod Pemberton wrote:
"Chris Torek" <no****@torek.net> wrote in message
news:e1********@news2.newsguy.com...
(Seriously: C89 specifically said that realloc(NULL,n) was equivalent
to malloc(n), and malloc(0) *could* be equivalent to malloc(1); it
then also said that realloc(p,0) was equivalent to free(p); so what
then is realloc(NULL,0) -- is it like malloc(0) and hence like
malloc(1), or is it just free(NULL)?)
If your question wasn't rhetorical, this realloc probably answers your
question. It has undefined behavior since it doesn't determine the 'magic mystery size' of s1...

void *my_realloc (void *s1, size_t size)
{
void *s2=NULL;

if (size!=0||s1==NULL)
s2 = malloc(size);
else
free(s1);
if (s1!=NULL)
memcpy(s2, s1, size);
return(s2);
}


Hmm, there seems to be something wrong with this my_realloc():

new_pointer = my_realloc(NULL, 100); /* ok */
new_pointer = my_realloc(NULL, 0); /* ok */
new_pointer = my_realloc(old_pointer, 100); /* old_pointer not free'd */


That's a simple fix:
if (s1!=NULL)
{
memcpy(s2, s1, size);
free(s1);
}
new_pointer = my_realloc(old_pointer, 0); /* memcpy(NULL, ????, 0); */
You've got that wrong. The last case is memcpy(new_pointer,old_pointer,0);
i.e., new_pointer = my_realloc(old_pointer, 0); /*
memcpy(new_pointer,old_pointer,0); */

If size is zero, s1 is freed (which doesn't set s1 to NULL) and s2 is
returned which is NULL.
In the last example, will the call to memcpy() invoke UB? Or, because
size is 0 (zero), it doesn't matter what the pointers point to?
As I said, you've got the last one wrong. No NULL is ever passed to
memcpy(), but a size zero is. To eliminate the size zero problem, you need
to know the old size, and check that it isn't zero. Which as Chris Torek's
example shows, it's based on compiler secrets.

The point of my reply was that Chris Torek's solution will pass NULL's for
'old' that _could_ "invoke" (I really don't like "invoke," it implies a
guaranted action...) UB for the first two situations:
new_pointer = my_realloc(NULL, 100); /* not Ok for ChrisT example*/
new_pointer = my_realloc(NULL, 0); /* not Ok for ChrisT example*/


(If you're keeping score, Chris has two UB, one size zero problem. And,
mine had one coding error, and one size zero problem.)

A closer corrected realloc, would be some merger of mine and Chris', with
zero correction for size:

void *realloc (void *s1, size_t size)
{
void *s2=NULL;
size_t oldsize = __some_sort_of_magic_done_here(old);

if (size!=0||s1==NULL)
s2 = malloc(size);
else
free(s1);
if (s1!=NULL)
{
size=oldsize<size?oldsize:newsize;
if(size==0)
size=1;
memcpy(s2, s1, size);
free(s1);
}
return(s2);
}
HTH,

Rod Pemberton


Apr 12 '06 #17

"Rod Pemberton" <do*********@sorry.bitbuck.cmm> wrote in message
news:e1**********@localhost.localdomain...

"Pedro Graca" <he****@dodgeit.com> wrote in message
news:sl*******************@ID-203069.user.individual.net...
Rod Pemberton wrote:
"Chris Torek" <no****@torek.net> wrote in message
news:e1********@news2.newsguy.com...
> (Seriously: C89 specifically said that realloc(NULL,n) was equivalent
> to malloc(n), and malloc(0) *could* be equivalent to malloc(1); it
> then also said that realloc(p,0) was equivalent to free(p); so what
> then is realloc(NULL,0) -- is it like malloc(0) and hence like
> malloc(1), or is it just free(NULL)?)

If your question wasn't rhetorical, this realloc probably answers your
question. It has undefined behavior since it doesn't determine the 'magic mystery size' of s1...

void *my_realloc (void *s1, size_t size)
{
void *s2=NULL;

if (size!=0||s1==NULL)
s2 = malloc(size);
else
free(s1);
if (s1!=NULL)
memcpy(s2, s1, size);
return(s2);
}
Hmm, there seems to be something wrong with this my_realloc():

new_pointer = my_realloc(NULL, 100); /* ok */
new_pointer = my_realloc(NULL, 0); /* ok */
new_pointer = my_realloc(old_pointer, 100); /* old_pointer not free'd */


That's a simple fix:
if (s1!=NULL)
{
memcpy(s2, s1, size);
free(s1);
}
new_pointer = my_realloc(old_pointer, 0); /* memcpy(NULL, ????, 0); */


You've got that wrong. The last case is

memcpy(new_pointer,old_pointer,0); i.e., new_pointer = my_realloc(old_pointer, 0); /*
memcpy(new_pointer,old_pointer,0); */

If size is zero, s1 is freed (which doesn't set s1 to NULL) and s2 is
returned which is NULL.
In the last example, will the call to memcpy() invoke UB? Or, because
size is 0 (zero), it doesn't matter what the pointers point to?
As I said, you've got the last one wrong. No NULL is ever passed to
memcpy(), but a size zero is. To eliminate the size zero problem, you

need to know the old size, and check that it isn't zero. Which as Chris Torek's example shows, it's based on compiler secrets.

The point of my reply was that Chris Torek's solution will pass NULL's for
'old' that _could_ "invoke" (I really don't like "invoke," it implies a
guaranted action...) UB for the first two situations:
new_pointer = my_realloc(NULL, 100); /* not Ok for ChrisT example*/ new_pointer = my_realloc(NULL, 0); /* not Ok for ChrisT
example*/
(If you're keeping score, Chris has two UB, one size zero problem. And,
mine had one coding error, and one size zero problem.)

A closer corrected realloc, would be some merger of mine and Chris', with
zero correction for size:

void *realloc (void *s1, size_t size)
{
void *s2=NULL;
size_t oldsize = __some_sort_of_magic_done_here(old);

if (size!=0||s1==NULL)
s2 = malloc(size);
else
free(s1);
if (s1!=NULL)
{
size=oldsize<size?oldsize:newsize;
Correction:
size=oldsize<size?oldsize:size;
if(size==0)
size=1;
memcpy(s2, s1, size);
free(s1);
}
return(s2);
}
HTH,

Rod Pemberton

Apr 12 '06 #18
Michael Wojcik wrote:

In article <sl*******************@ID-203069.user.individual.net>, Pedro Graca <he****@dodgeit.com> writes:
Michael Wojcik wrote:
> The result of realloc should always be stored in a temporary
> variable and should be checked for null. If it is null, remember
> to free the old value:
>
> char *newkey;
> newkey = realloc(key, p);
> if (! newkey)
> {
> free(key);
> [perform error handling]
> }
> key = newkey;


Uh? Doesn't realloc(), when it doesn't fail, call free() all by itself
if there's a need for that? Also suppose the reallocated memory doesn't
'move' (newkey == key); doing a "free(key);" now could be disastrous.


The code above only frees key if realloc failed.


I think I finally understand why I saw something wrong in that code.

If the reallocation fails and NULL is assigned to newkey, it's supposed
that the "[perform error handling]" doesn't return, so the code will
never get to the "key = newkey;" statement.
I was imagining that the code would go on, and didn't understand the
need to "free(key);" and lose all references to its memory.

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Apr 12 '06 #19
Rod Pemberton wrote:
"Pedro Graca" <he****@dodgeit.com> wrote in message
news:sl*******************@ID-203069.user.individual.net...
Rod Pemberton wrote:
> void *my_realloc (void *s1, size_t size)
> {
> void *s2=NULL;
>
> if (size!=0||s1==NULL)
> s2 = malloc(size);
> else
> free(s1);
> if (s1!=NULL)
> memcpy(s2, s1, size); free(s1); > return(s2);
> }
Hmm, there seems to be something wrong with this my_realloc():

new_pointer = my_realloc(NULL, 100); /* ok */
new_pointer = my_realloc(NULL, 0); /* ok */
new_pointer = my_realloc(old_pointer, 100); /* old_pointer not free'd */


That's a simple fix:

[fix incorporated in the code above, check '>' marks]
new_pointer = my_realloc(old_pointer, 0); /* memcpy(NULL, ????, 0); */


You've got that wrong. The last case is memcpy(new_pointer,old_pointer,0);
i.e., new_pointer = my_realloc(old_pointer, 0); /*
memcpy(new_pointer,old_pointer,0); */

If size is zero, s1 is freed (which doesn't set s1 to NULL) and s2 is
returned which is NULL.


Right. Let's run "my_realloc(valid_old_pointer, 0);" step by step ...

void *my_realloc (void *s1, size_t size)
{
void *s2=NULL;
/* s1 --> valid_old_pointer
* s2 --> NULL
* size --> 0 */

if (size!=0||s1==NULL)
s2 = malloc(size);
else
free(s1);
/* s1 --> free'd valid_old_pointer
* s2 --> NULL
* size --> 0 */

if (s1!=NULL)
memcpy(s2, s1, size);
/* And here we go ...
* s2 is NULL, s1 is the free'd valid_old_pointer, size is 0
* so
*
* ...
*
* memcpy(NULL, ????, 0); */

return(s2);
}
In the last example, will the call to memcpy() invoke UB? Or, because
size is 0 (zero), it doesn't matter what the pointers point to?


As I said, you've got the last one wrong. No NULL is ever passed to
memcpy(), but a size zero is.


Where did I go wrong in my step-by-step run of my_realloc()?
To eliminate the size zero problem, you need
to know the old size, and check that it isn't zero. Which as Chris Torek's
example shows, it's based on compiler secrets.


Yes, I understand this is nothing more than an exercise in second
guessing the compiler secrets ... but I feel it's a good exercise to aid
in developing my knowledge of C.

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Apr 12 '06 #20

"Pedro Graca" <he****@dodgeit.com> wrote in message
news:sl*******************@ID-203069.user.individual.net...
Rod Pemberton wrote:
"Pedro Graca" <he****@dodgeit.com> wrote in message
news:sl*******************@ID-203069.user.individual.net...
Right. Let's run "my_realloc(valid_old_pointer, 0);" step by step ...

void *my_realloc (void *s1, size_t size)
{
void *s2=NULL;
/* s1 --> valid_old_pointer
* s2 --> NULL
* size --> 0 */

if (size!=0||s1==NULL)
s2 = malloc(size);
else
free(s1);
/* s1 --> free'd valid_old_pointer
* s2 --> NULL
* size --> 0 */


Correct to here.
if (s1!=NULL)
memcpy(s2, s1, size);
/* And here we go ...


No we don't. s1!=NULL is true. This if() is skipped. s1 is freed, but is
_NOT_ NULL. It retains it's prior value. Why? Because, the argument to
free() is passed by value. That means s1 isn't changed.

free() is declared as:
void free(void *ptr);

For free() to return a NULL as you seem to think, it'd need to be declared
as (this would also change the way it is called):
void free(void **ptr);

HTH,
Rod Pemberton
Apr 13 '06 #21

"Rod Pemberton" <do*********@sorry.bitbuck.cmm> wrote in message
news:e1**********@localhost.localdomain...

"Pedro Graca" <he****@dodgeit.com> wrote in message
news:sl*******************@ID-203069.user.individual.net...
Rod Pemberton wrote:
"Pedro Graca" <he****@dodgeit.com> wrote in message
news:sl*******************@ID-203069.user.individual.net...


Right. Let's run "my_realloc(valid_old_pointer, 0);" step by step ...

void *my_realloc (void *s1, size_t size)
{
void *s2=NULL;
/* s1 --> valid_old_pointer
* s2 --> NULL
* size --> 0 */

if (size!=0||s1==NULL)
s2 = malloc(size);
else
free(s1);
/* s1 --> free'd valid_old_pointer
* s2 --> NULL
* size --> 0 */


Correct to here.
if (s1!=NULL)
memcpy(s2, s1, size);
/* And here we go ...


Sorry, you're right. _I_ must have been thinking free NULLed ...

RP
Apr 13 '06 #22

"Rod Pemberton" <do*********@sorry.bitbuck.cmm> wrote in message
news:e1**********@localhost.localdomain...

"Rod Pemberton" <do*********@sorry.bitbuck.cmm> wrote in message
news:e1**********@localhost.localdomain...

"Pedro Graca" <he****@dodgeit.com> wrote in message
news:sl*******************@ID-203069.user.individual.net...
Rod Pemberton wrote:
> "Pedro Graca" <he****@dodgeit.com> wrote in message
> news:sl*******************@ID-203069.user.individual.net...

Sorry, you're right. _I_ must have been thinking free NULLed ...


Pedro, is this one any better?

void *my_realloc (void *s1, size_t size)
{
void *s2=NULL;

if(size!=0)
s2 = malloc(size);
if(s1!=NULL&&size!=0)
memcpy(s2, s1, size);
if(s1!=NULL)
free(s1);
return(s2);
}
Rod Pemberton
Apr 13 '06 #23
Rod Pemberton wrote:
Rod Pemberton
Pedro Graca

[snip a lot of confusion]

Now that /that/ is taken care of ... -- but I may still come back to it
in a day or two :)
Does this program

#include <stdlib.h>
#include <string.h>
int main(void) {
void * ptr = malloc(42);
if (ptr) {
free(ptr);

memcpy(NULL, ptr, 0);
memcpy(ptr, NULL, 0);
}
return 0;
}

invoke UB at any point?

Or, because the number of bytes "to copy" is 0 (zero) it doesn't matter
what the pointers point to?

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Apr 13 '06 #24
Pedro Graca said:
Does this program

#include <stdlib.h>
#include <string.h>
int main(void) {
void * ptr = malloc(42);
if (ptr) {
free(ptr);

memcpy(NULL, ptr, 0);
memcpy(ptr, NULL, 0);
}
return 0;
}

invoke UB at any point?
Four points.
Or, because the number of bytes "to copy" is 0 (zero) it doesn't matter
what the pointers point to?


It matters. The definition of memcpy requires that the two pointer
parameters each point to an object. NULL does not point to an object (and,
indeed, is *guaranteed* not to point to an object). Furthermore, the value
of ptr is indeterminate, and yet you are evaluating it. This evaluation
takes place *before* memcpy is even called.

Therefore, and for two different reasons, the behaviour is undefined,
irrespective of the number of bytes to be copied.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Apr 13 '06 #25
>"Chris Torek" <no****@torek.net> wrote in message
news:e1********@news2.newsguy.com...
With a few exceptions (noted below), realloc() is essentially an
optimized version of the following:

void *realloc(void *old, size_t newsize) {
size_t oldsize = __some_sort_of_magic_done_here(old);
void *new;

new = malloc(newsize);
if (new != NULL) {
memcpy(new, old, oldsize < newsize ? oldsize : newsize);
free(old);
}
return new;
}
In article <e1**********@localhost.localdomain>,
Rod Pemberton <do*********@sorry.bitbuck.cmm> wrote:
Hmm, no NULL check for old?
I was (admittedly sloppily/non-Standard-ly) omitting it on the
assumption that memcpy(new, NULL, 0) would be a no-op rather than
causing problems. Better to check. Of course, a "real" realloc()
(a) has to supply the "magic" that figures out the old size, and
(b) should (but does not have to) optimize those cases where the
realloc can be done without copying. The intent was really just
to show "minimal required behavior", as it were.
(Seriously: C89 specifically said that realloc(NULL,n) was equivalent
to malloc(n), and malloc(0) *could* be equivalent to malloc(1); it
then also said that realloc(p,0) was equivalent to free(p); so what
then is realloc(NULL,0) -- is it like malloc(0) and hence like
malloc(1), or is it just free(NULL)?)

If your question wasn't rhetorical, this realloc probably answers your
question. [code snipped]


Alas, no code can answer the question unless that code comes in
the form of a response to a Defect Report to the C standards people.

The problem is that the text of the Standard is written in a
semi-formal English, leaving some items ambiguous. Sometimes the
ambiguity is intentional, to allow different implementations to do
different things. Sometimes it is, I think at least, just pointless
ambiguity. (The *answer* to my question is not usually very
interesting, though. I tend not to realloc() to size 0 and therefore
not care what it might or might not do.)

(I understand why the Standards folks did not want to use something
more formal -- whether mathematical notation or actual code -- to
define things. I think it was at least occasionally the wrong
decision, though. It would be possible to specify things precisely,
then use English text to relax the requirements, instead of using
English to specify things laxly. That might reduce the flexibility
to implementors, but it could greatly improve the predictability to
users.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Apr 13 '06 #26
Rod Pemberton wrote:
Pedro, is this one any better?

[snip my_realloc() implementation]

Yes :)
But I'm not the best guy around here to be asked stuff.

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Apr 13 '06 #27

"Chris Torek" <no****@torek.net> wrote in message
news:e1*********@news1.newsguy.com...
"Chris Torek" <no****@torek.net> wrote in message
news:e1********@news2.newsguy.com...
With a few exceptions (noted below), realloc() is essentially an
optimized version of the following:

In article <e1**********@localhost.localdomain>,
Rod Pemberton <do*********@sorry.bitbuck.cmm> wrote:
Hmm, no NULL check for old?


I was (admittedly sloppily/non-Standard-ly) omitting it on the
assumption that memcpy(new, NULL, 0) would be a no-op rather than
causing problems. Better to check. Of course, a "real" realloc()
(a) has to supply the "magic" that figures out the old size, and
(b) should (but does not have to) optimize those cases where the
realloc can be done without copying. The intent was really just
to show "minimal required behavior", as it were.


That's why I mentioned: "If your question wasn't rhetorical."
Unfortunately, Pedro had to beat me up pretty good to get me to realize I
wasn't reading my code as written, but thinking my code as I thought it
worked when I wrote it... :-(
The problem is that the text of the Standard is written in a
semi-formal English, leaving some items ambiguous. Sometimes the
ambiguity is intentional, to allow different implementations to do
different things. Sometimes it is, I think at least, just pointless
ambiguity. (The *answer* to my question is not usually very
interesting, though. I tend not to realloc() to size 0 and therefore
not care what it might or might not do.)

The problem is that they stripped the historical context and the "C is built
upon assembly language" context that helped define earlier C
implementations. There are things in the C89/90 spec. that I'm sure were
upper boundaries for 16-bit compilers. Unfortunately, people who didn't use
C in the '80s or early 90's usually think they are the lower boundaries.
The spec. of course is sufficiently vauge that they can be upper boundaries
for a 16-bit compiler and lower boundaries for a 32-bit one.
(I understand why the Standards folks did not want to use something
more formal -- whether mathematical notation or actual code -- to
define things. I think it was at least occasionally the wrong
decision, though. It would be possible to specify things precisely,
then use English text to relax the requirements, instead of using
English to specify things laxly. That might reduce the flexibility
to implementors, but it could greatly improve the predictability to
users.)


Even here most people say: "It invokes undefined behavior." "Invokes" to me
implies a guaranteed result. It's closer to "will cause" than "may cause."
Unfortunately or fortunately, almost all cases of UB work as intended and
don't cause any blatantly obvious defect like a crash, lockup, or memory
corruption.
Rod Pemberton
Apr 14 '06 #28

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

36
by: Roy | last post by:
Hi all : My code below : #include <stdio.h> #include <string.h> #include <stdlib.h> char *cat(char *s, const char *t) { char *tmp;
9
by: James S. Singleton | last post by:
If we do q = realloc(p, 128) ; and on (successful) return of realloc, q != p, must the block pointed to by p be explicitly freed, or has realloc freed it already?
10
by: James S. Singleton | last post by:
Thanks everybody for your replies. I gather that: a) How to obtain the size of the memory region pointed to by ptr in realloc(ptr, size) is implementation-dependent. b) Implementing...
4
by: alex323 | last post by:
Hey. I must have an array that can be resized dynamically. I have coded an implementation of it using malloc/realloc, but I am getting a runtime error as seen below in GDB: *** glibc detected...
28
by: bwaichu | last post by:
Is it generally better to set-up a buffer (fixed sized array) and read and write to that buffer even if it is larger than what is being written to it? Or is it better to allocate memory and...
2
by: solanki.chandrakant | last post by:
hi i have fedora linux 4 and i have simple realloc program which i am included here... plz help me to overcome the realloc to pointer to character variable. The program working 2 times but more...
64
by: Robert Seacord | last post by:
The C standard doesn't say anything about what happens when you call realloc with a size argument of 0. Both glibc and openbsd appear to return a valid pointer to a zero-sized object.. e.g. the...
29
by: marvinla | last post by:
Hello! I'm a beginner in C, and I'm having trouble with a pointer-to-pointer reallocation. This piece of code works well, but Valkyrie warns some parts (pointed below), and is breaking my real...
7
by: lancer6238 | last post by:
Hi, I'm writing a program that separates a set of integers into groups and then quicksort each group individually. However, I'm having problems with my realloc() function. (Pardon me if the...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.