when can realloc fail?

B

banansol

Hi,
I just want to get this right.
A call to realloc() will return NULL on error and the original memory
is left untouched,
both when requesting a larger or a smaller size that the original,
right?
But a call to realloc() with size set to zero is equivalent to free(),
with returns void.
Does that mean that a call to realloc() can fail when shinking memory
except when
shrinking it to zero in which case it will always succeed?

Thanks!
 
E

Eric Sosman

Hi,
I just want to get this right.
A call to realloc() will return NULL on error and the original memory
is left untouched,
both when requesting a larger or a smaller size that the original,
right?
But a call to realloc() with size set to zero is equivalent to free(),
with returns void.
Does that mean that a call to realloc() can fail when shinking memory
except when
shrinking it to zero in which case it will always succeed?

Yes, realloc() can fail when shrinking an allocation, or
when growing it, or even when leaving its size unchanged.

When reallocating to zero size, the situation is complicated.
C90 says "If size is zero and ptr is not a null pointer, the
object it points to is freed." Since free() cannot fail (given
an argument that doesn't invoke undefined behavior), it follows
that realloc(...,0) cannot fail.

But C99 has no such text, and makes no special case for size
zero. All we're told is that realloc(...,0) either fails or it
returns a pointer to an object of size zero. Nothing I can find
in C99 forbids realloc(...,0) to fail, so presumably it can.
 
S

santosh

Hi,
I just want to get this right.
A call to realloc() will return NULL on error

The word failure might be more appropriate in this context than the
word error.
and the original memory is left untouched,
both when requesting a larger or a smaller size that the original, right?
Yes.

But a call to realloc() with size set to zero is equivalent to free(),

Semantically yes.
with returns void.

No, it returns an indeterminate value.
Does that mean that a call to realloc() can fail when shinking memory except when
shrinking it to zero in which case it will always succeed?

No. realloc is not guaranteed to suceed even when the new size is zero.
 
B

banansol

Yes, realloc() can fail when shrinking an allocation, or
when growing it, or even when leaving its size unchanged.

When reallocating to zero size, the situation is complicated.
C90 says "If size is zero and ptr is not a null pointer, the
object it points to is freed." Since free() cannot fail (given
an argument that doesn't invoke undefined behavior), it follows
that realloc(...,0) cannot fail.

But C99 has no such text, and makes no special case for size
zero. All we're told is that realloc(...,0) either fails or it
returns a pointer to an object of size zero. Nothing I can find
in C99 forbids realloc(...,0) to fail, so presumably it can.

Thank you for your reply!
But I wonder, if realloc(...,0) fails in C99, how can I know that?
How can I know if a returned NULL means that realloc() failed,
or if it is the pointer to the new memory, empty, which is NULL.
(That is what I got on my compiler anyway)
 
B

banansol

The word failure might be more appropriate in this context than the
word error.


Semantically yes.


No, it returns an indeterminate value.

What? My manpage says "void free(void *ptr);",
doesn't free return void? By that I meant, free doesn't return
anything.
No. realloc is not guaranteed to suceed even when the new size is zero.

And as I wrote in the other post, I wonder how I can know that.
 
S

santosh

What? My manpage says "void free(void *ptr);",
doesn't free return void? By that I meant, free doesn't return
anything.

You're correct. But realloc with a new size of zero either returns a
null pointer, upon failure, or returns an indeterminate value.
And as I wrote in the other post, I wonder how I can know that.

If the reallocation to zero size suceeds, an indeterminate pointer
value is returned, if it fails, a null pointer value is returned and
the original block is unchanged.
 
H

Hallvard B Furuseth

But I wonder, if realloc(...,0) fails in C99, how can I know that?

I asked on comp.std.c recently. In C99, realloc returns NULL if and
only if it fails. You'll see it if you read the C99 text without
expecting compatibliity with the C89 realloc(,0) behavior.
How can I know if a returned NULL means that realloc() failed,
or if it is the pointer to the new memory, empty, which is NULL.

Just avoid realloc(, 0).

In theory, you can check '#if __STDC_VERSION__ >= 199901L' to see if you
have a C99 compiler. In practice, that doesn't tell you if you have a
C99 _library_: You might have a compiler like gcc which has both C99 and
C89 mode, but uses the system C library in either case.
 
B

banansol

You're correct. But realloc with a new size of zero either returns a
null pointer, upon failure, or returns an indeterminate value.



If the reallocation to zero size suceeds, an indeterminate pointer
value is returned, if it fails, a null pointer value is returned and
the original block is unchanged.

In that case there is something strange here, if I compile this in gcc

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char *ptr = malloc(42);
if (realloc(ptr, 0) == NULL)
printf("realloc failed\n");
return 0;
}

I always get "realloc failed" printed, in both c89 and c99 mode.
I wouldn't expect it everytime as it does here.
Anyway, I will use free() instead, to avoid confusion.
Thanks for the help!
 
B

Barry Schwarz

Hi,
I just want to get this right.
A call to realloc() will return NULL on error and the original memory
is left untouched,
both when requesting a larger or a smaller size that the original,
right?

It returns NULL if the space cannot be allocated. Whether it is due
to an error or not is something else.
But a call to realloc() with size set to zero is equivalent to free(),
with returns void.

No it is not. Read the last sentence of 7.20.3 again.
Does that mean that a call to realloc() can fail when shinking memory
except when
shrinking it to zero in which case it will always succeed?

No. Success is not guaranteed.


Remove del for email
 
C

CBFalconer

.... snip ...

In that case there is something strange here, if I compile this in gcc

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char *ptr = malloc(42);
if (realloc(ptr, 0) == NULL)
printf("realloc failed\n");
return 0;
}

That depends on your library, not gcc. I consider libraries that
do that as poorly implemented, although legal.
 
M

Malcolm McLean

Hi,
I just want to get this right.
A call to realloc() will return NULL on error and the original memory
is left untouched,
both when requesting a larger or a smaller size that the original,
right?
But a call to realloc() with size set to zero is equivalent to free(),
with returns void.
Does that mean that a call to realloc() can fail when shinking memory
except when
shrinking it to zero in which case it will always succeed?
It is a bit of a grey area.

Normally you want the construct

temp = realloc(ptr, newsize);
if(temp == 0)
{
fprintf(stderr, "Oh no, out of memory\n");
free(ptr);
return -1;
}
ptr = temp;
..... /* do something useful */
free(ptr);
return 0;

it is quite a lot of code simply to perform memory management. However if
newsize is zero you've entered a grey area. temp could be zero or a valid
pointer assuming that the function doesn't fail. If we say that realloc()
must return a pointer to a block of no memory then you've also got the
potential for a fail. Then it is not unlikely that your code, knowing that
newsize is zero and it is working on an empty data set, will forget to call
free() on ptr.
 
O

Old Wolf

But realloc with a new size of zero either returns a
null pointer, upon failure, or returns an indeterminate value.

I don't see any text in the standard to support this.

In fact, it seems absurd, as undefined behaviour would
be caused as soon as the user checked or stored the
return value.

The text in 7.20.3.4 in C99 only says that the items pointed
to by the return value are indeterminate.
 
N

Nelu

Thank you for your reply!
But I wonder, if realloc(...,0) fails in C99, how can I know that?
How can I know if a returned NULL means that realloc() failed,
or if it is the pointer to the new memory, empty, which is NULL.
(That is what I got on my compiler anyway)

In C99 it only returns NULL when it fails. If it returns non-null
and the size is 0 then it will return an address to a block of
memory of zero size. The address *will not be NULL* and you will
have to free it using free().
 
C

CBFalconer

Nelu said:
.... snip ...

In C99 it only returns NULL when it fails. If it returns non-null
and the size is 0 then it will return an address to a block of
memory of zero size. The address *will not be NULL* and you will
have to free it using free().

Not so. C99 specifically allows a successfull realloc(p, 0) or
malloc(0) to return NULL. I consider systems that use this to be
flawed, yet portable code has to allow for it.
 
E

Eric Sosman

CBFalconer said:
Nelu wrote:
... snip ...

Not so. C99 specifically allows a successfull realloc(p, 0) or
malloc(0) to return NULL. I consider systems that use this to be
flawed, yet portable code has to allow for it.

Could you point out where this is allowed? I can see
that it's permitted for realloc(NULL, 0), but can't find any
such dispensation for realloc(p, 0) where p!=NULL.
 
P

pete

Eric said:
Could you point out where this is allowed? I can see
that it's permitted for realloc(NULL, 0), but can't find any
such dispensation for realloc(p, 0) where p!=NULL.

N869
7.20.3 Memory management functions
[#1]

If the size of the space requested is zero,
the behavior is implementation-defined: either a null
pointer is returned, or the behavior is as if the size were
some nonzero value, except that the returned pointer shall
not be used to access an object.
 
N

Nelu

CBFalconer said:
Nelu wrote:
.... snip ...

Not so. C99 specifically allows a successfull realloc(p, 0) or
malloc(0) to return NULL. I consider systems that use this to be
flawed, yet portable code has to allow for it.

Where?

n1124:
7.20.3.3-4
Returns:
"The realloc function returns a pointer to the new object (which
may have the same
value as a pointer to the old object), or a null pointer if the
new object could not be
allocated."

Now, *malloc* is different: "The malloc function returns either a
null pointer or a pointer to the allocated space.". I think this
means that it will have to return NULL if it fails (a non-null
pointer must point to the allocated space, but the allocation
failed), but it could probably be successful in allocating space
and still return NULL.

7.20.3-1 says:
"If the size of the space requested is zero, the behavior is
implementation defined:
either a null pointer is returned, or the behavior is as if the
size were some
nonzero value, except that the returned pointer shall not be used
to access an object."
So, yes, realloc(.., 0) can return NULL but the definition of
realloc forces specifies NULL as failure to allocate the new
object. On malloc there's no such specification.
 
P

pete

Nelu wrote:
Now, *malloc* is different: "The malloc function returns either a
null pointer or a pointer to the allocated space.". I think this
means that it will have to return NULL if it fails (a non-null
pointer must point to the allocated space, but the allocation
failed), but it could probably be successful in allocating space
and still return NULL.

malloc can't be successful in allocating space
and still return NULL.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top