How to check whether malloc has allocated memory properly in case ifmalloc(0) can return valid point

  • Thread starter Shivanand Kadwadkar
  • Start date
S

Shivanand Kadwadkar

i want to check after calling malloc whether allocation is successful
or not. previously i have done like

ptr=malloc(size);

if(ptr==NULL)

But i came to know malloc can return valid pointer in case if argument
is zero.

one solution is

if(size==0)
ptr=NULL;
else
ptr=malloc(size);

if you have any other suggestion please welcome.
 
M

Mark Bluemel

i want to check after calling malloc whether allocation is successful
or not. previously i have done like

ptr=malloc(size);

if(ptr==NULL)

But i came to know malloc can return valid pointer in case if argument
is zero.

And that pointer can successfully be passed to free(). And you are
certain to be able to store at least zero bytes at the location pointed
to by the pointer, so what's the problem?

If the issue is that you are likely to call malloc() with an argument of
zero and then attempt to store data at the address returned, your
problem is not really with malloc() is it?

I think it would be useful for you to explain in more detail what
problem you think you need help with, as I'm not at all clear about that.
 
B

BartC

Mark Bluemel said:
And that pointer can successfully be passed to free(). And you are certain
to be able to store at least zero bytes at the location pointed to by the
pointer, so what's the problem?

One issue might be that, if you call malloc(0) enough times, you can run out
of memory!
 
M

Malcolm McLean

If the issue is that you are likely to call malloc() with an argument of
zero and then attempt to store data at the address returned, your
problem is not really with malloc() is it?
The code could be like this

employees = malloc(N * sizeof(struct Employee));
if(!employees)
goto error_handler;
memcpy(employees, temparray, N * sizeof(struct Employee));

the code is correct is malloc() returns non-zero for a zero allocation
and N == 0 is allowed. It's incoorect is malloc() returns zero in this
situation.
 
T

Tom St Denis

The code could be like this

employees = malloc(N * sizeof(struct Employee));
if(!employees)
  goto error_handler;
memcpy(employees, temparray, N * sizeof(struct Employee));

the code is correct is malloc() returns non-zero for a zero allocation
and N == 0 is allowed. It's incoorect is malloc() returns zero in this
situation.

if (N) {
employees = calloc(N, sizeof *employees);
if(!employees) {
goto error_handler;
}
memcpy(employees, temparray, N * sizeof *employees);
} else {
employees = NULL;
}

There I both fixed the problem and cleaned up your code, that'll be
100 shillings please, due net 30.

Tom
 
E

Eric Sosman

i want to check after calling malloc whether allocation is successful
or not. previously i have done like

ptr=malloc(size);

if(ptr==NULL)

But i came to know malloc can return valid pointer in case if argument
is zero.

Yes: Just like malloc(N), malloc(0) can return NULL or non-NULL.
Whichever it returns, though, you must not try to read or store through
that pointer. If it's NULL, well, you mustn't try to read or store
through NULL. If it's non-NULL you can read or store anything whose
size does not exceed the argument value, but since *every* C data type
is at least one byte wide there is nothing that fits in 0 bytes, hence
nothing you can safely store in 0 bytes.

To test for "success" of malloc(N), you could write

ptr = malloc(N);
if (ptr == NULL && N > 0) {
// failure
} else {
// "success"
}

I put "success" in quotes because of an ambiguity that is meaningless
in practice: If malloc(0) returns NULL, we cannot tell whether it
"succeeded" or "failed," but it really doesn't make any difference.
one solution is

if(size==0)
ptr=NULL;
else
ptr=malloc(size);

After this, a simple `if (ptr == NULL)' leaves you with the same
problem you had to begin with.
if you have any other suggestion please welcome.

One thing to keep in mind is that this `size' value comes from
somewhere, and will (presumably) govern what you later try to store
in the allocated area. If your program can calculate `size' as 0,
it should also never try to store more than 0 bytes in the allocated
area -- in which case, all will be well no matter what malloc(0)
returned.

Since a 0-byte memory area is mostly useless, you probably should
not be allocating a large number of them -- if you are, you've most
likely got a bug somewhere. Usually, 0-byte allocations arise when
you've got a data structure whose size you adjust up and down as the
circumstances require. Maybe you're keeping track of employees'
birthdays using 366 dynamically-allocated blocks, and the only person
born on February 29 quits: Your program might do

count[date] -= 1; // making it zero
Person *tmp = realloc(persons[date], count[date] * size *tmp);
if (tmp == NULL && count[date] > 0) {
// Can't delete: Hire him back again!
} else {
persons[date] = tmp;
}

In situations like this, a 0-byte allocation could be considered
"normal." But if you're routinely making thousands and thousands of
0-byte allocations, there's likely something wrong elsewhere.
 
J

Joachim Schmitz

Shivanand said:
i want to check after calling malloc whether allocation is successful
or not. previously i have done like

ptr=malloc(size);

if(ptr==NULL)

But i came to know malloc can return valid pointer in case if argument
is zero.

one solution is

if(size==0)
ptr=NULL;
else
ptr=malloc(size);

if you have any other suggestion please welcome.

IMHO the case when malloc(0) return NULL is more interesting, as there you
need to adjust the error checking, i.e. not exit the program due to lack of
memory if size was 0.

Bye, Jojo
 
T

Tom St Denis

IMHO the case when malloc(0) return NULL is more interesting, as there you
need to adjust the error checking, i.e. not exit the program due to lack of
memory if size was 0.

Agreed, I can't ever think of a legit use for malloc'ing zero bytes.
It should return a NULL to trip up [what should be in place] normal
error detection.
 
A

August Karlstrom

i want to check after calling malloc whether allocation is successful
or not. previously i have done like

ptr=malloc(size);

if(ptr==NULL)

But i came to know malloc can return valid pointer in case if argument
is zero.

one solution is

if(size==0)
ptr=NULL;
else
ptr=malloc(size);

if you have any other suggestion please welcome.

If possible I would design the program so that `size' is only allowed to
be a positive number. If it is a library I would simply assert that size
> 0 and put the responsibility on the client to make sure that the
condition is met (the fail fast strategy).


/August
 
J

Jens Thoms Toerring

Ered China Luin said:
You are also allowed to envelope malloc and allocations for your own use.
For example allocate could add an extra 4 bytes before and after with a
check pattern, with dispose verifying that to try to find block overruns.

I would be a bit careful with putting stuff at the start of the
allocated area - if you put e.g. 4 bytes at the start and then
use the original address + 4 then this may not be properly aligned
for all possible types. You can be only be sure about that for the
original address returned by malloc().

Regards, Jens
 
E

Eric Sosman

Since I have up to 50 gigabytes of memory available, I don't bother checking.
I'mh appy risking an abort on memory address.


(1) Decide exactly what you want malloc to return under all possible conditions.

(2) Write your own allocator in front of malloc. Perhaps something like

static char empty = 0;
void *allocate(int n) {return n==0 ?&empty : malloc(n);}
void dispose(void *p) {if (p!=&empty) free(p);}

You can do this in your own program if you like, but note that
malloc(0) itself cannot work this way. If it returns non-NULL, it
must return a value that is distinct from all the other values it
has returned (that have not yet been released). That is, malloc(0)
must satisfy:

void *p = malloc(0);
void *q = malloc(0);
assert (p == NULL || p != q);

Of course, you can make your wrapper behave as you please -- but
you can't change the behavior of the underlying malloc().
 
E

Eric Sosman

[...]
The current interface means you don't have to special case zero. You can
allocate and process n bytes for n==0 as well n>0 with the same code. For example

ptr p = memcpy(malloc(n), src, n);

Careful! This has undefined behavior if malloc(n) returns NULL,
even if n is zero. See 7.21.1p2 and 7.1.4p1, and note the absence of
any "explicitly stated otherwise" language in 7.21.2.1.

In other words: You needn't special-case zero (much), but you
still need the NULL test.
This is similar to the old zero trip loops of Fortran and Algol; both languages
could implement identical semantics, but which had the more of convenient syntax
was a matter of taste.

In the long-ago days when I used FORTRAN (II and IV), it had
no construct I'd have described as a "zero-trip loop." Specifically,
a DO loop always executed its body at least once.
 
J

Joachim Schmitz

Tom said:
IMHO the case when malloc(0) return NULL is more interesting, as
there you need to adjust the error checking, i.e. not exit the
program due to lack of memory if size was 0.

Agreed, I can't ever think of a legit use for malloc'ing zero bytes.
It should return a NULL to trip up [what should be in place] normal
error detection.

That is not my point. Of course malloc(0) is stupid, but calculating the
size of a buffer and then malloc()'ing that is legel, even of the size
calculation mey result in 0. But in that case chacking malloc() for
returning NULL is not sufficient for aborting the program, you'd also need
to check size, either before the malloc (and skip it) or after, but befor
jumping to the error handling.

I once had to debug a program, actually 'nm', which aborted with a memory
error on an objectfile, that, as it turned out later, had 0 symbols (which
is not usual, but legal), and so 'nm' successfully malloc()'ed 0 bytes, but
chocked on the NULL check.

Bye, Jojo
 
G

Gerald Breuer

As a memory-block with sizer 0 isn't touched
you don't need to care for this case explicitly.
 
E

Eric Sosman

Eric Sosman said:
[...]
(2) Write your own allocator in front of malloc. Perhaps something like

static char empty = 0;
void *allocate(int n) {return n==0 ?&empty : malloc(n);}
void dispose(void *p) {if (p!=&empty) free(p);}

You can do this in your own program if you like, but note that
malloc(0) itself cannot work this way. If it returns non-NULL, it
must return a value that is distinct from all the other values it

And you can change it to
void *allocate(int n) {return malloc(n==0 ? 1 : n);}

That works. It's silly, IMHO, but it works. (Keep in mind that
`int' and `size_t' are not synonymous, so you may be inviting trouble
with your choice of parameter type.)
And I can hide that malloc if I want.

Not sure what you mean by "hide." You cannot "hide" it in the
sense of making it unavailable to other code in the program, nor can
you "hide" it in the sense of intercepting all malloc() calls and
routing them somewhere other than to the real malloc(). You can, of
course, threaten to flog or "hide" or "give a hiding to" anyone who
calls malloc() directly instead of using your wrapper -- but that's
social engineering, not software engineering.
 
E

Eric Sosman

Eric Sosman said:
[...]
This is similar to the old zero trip loops of Fortran and Algol; [...]

In the long-ago days when I used FORTRAN (II and IV), it had
no construct I'd have described as a "zero-trip loop." Specifically,
a DO loop always executed its body at least once.

I had it very early on.

if (n.eq.0) goto 11
do 10 i=1,n
...
10 continue
11 continue

The phrase "duck and cover" springs to mind.

That's not a "zero-trip loop," it's an ordinary loop conditionally
skipped. (And it still iterates once for n=-42.) (And it's not "very
early on," because the "logical IF" wasn't in the language prior to
FORTRAN IV.)
 
B

BartC

Eric Sosman said:
Eric Sosman said:
On 12/16/2010 11:04 AM, Ered China Luin wrote:
[...]
This is similar to the old zero trip loops of Fortran and Algol; [...]

In the long-ago days when I used FORTRAN (II and IV), it had
no construct I'd have described as a "zero-trip loop." Specifically,
a DO loop always executed its body at least once.

I had it very early on.

if (n.eq.0) goto 11
do 10 i=1,n
...
10 continue
11 continue

The phrase "duck and cover" springs to mind.

That's not a "zero-trip loop," it's an ordinary loop conditionally
skipped. (And it still iterates once for n=-42.) (And it's not "very
early on," because the "logical IF" wasn't in the language prior to
FORTRAN IV.)

Fortran IV came out nearly 50 years ago. How much earlier do you want to go?
 
E

Eric Sosman

Eric Sosman said:
On 12/16/2010 11:04 AM, Ered China Luin wrote:
[...]
This is similar to the old zero trip loops of Fortran and Algol; [...]

In the long-ago days when I used FORTRAN (II and IV), it had
no construct I'd have described as a "zero-trip loop." Specifically,
a DO loop always executed its body at least once.

I had it very early on.

if (n.eq.0) goto 11
do 10 i=1,n
...
10 continue
11 continue

The phrase "duck and cover" springs to mind.

That's not a "zero-trip loop," it's an ordinary loop conditionally
skipped. (And it still iterates once for n=-42.) (And it's not "very
early on," because the "logical IF" wasn't in the language prior to
FORTRAN IV.)

Fortran IV came out nearly 50 years ago. How much earlier do you want to
go?

"Nearly 50 years ago" FORTRAN IV was available on a handful of
computers. In late 1966 (44 < 50 years ago) I was writing my first
programs in FORTRAN II.

Fortran, with its newfangled mixed-case name (note that even C has
not yet advanced to a mixed-case name), didn't arrive until 1991. By
then, CALL EXIT was a vanished speck in my personal rear-view mirror.

FORTRAN (NO SUFFIX) was altogether before my time, though.
 
R

Ralph Spitzner

Tom said:
On Dec 16, 6:38 am, Malcolm McLean<[email protected]>
if (N) {
employees = calloc(N, sizeof *employees);
if(!employees) {
break;
//> goto error_handler;
}
memcpy(employees, temparray, N * sizeof *employees);
} else {
employees = NULL;
}

if(N && (employees == NULL))
{
do_something_here();
}
There I both fixed the problem and cleaned up your code, that'll be
100 shillings please, due net 30.

Tom

only 30 shillings, 70 go for the goto :p

-rasp
 
A

arnuld

One issue might be that, if you call malloc(0) enough times, you can run
out of memory!

I tried this and it hanged my system in 60 seconds. Last thing I could
see from top commnd (Linux) after 40 or so seconds that memory usage was
jumping between 83-87% range and CPU u]2sage was 13-17% range and then I
switched to Emacs from urxvt, to look at source code and moved the cursor
10 lines down and then everything just jammed, had to give a hard reboot.

If malloc was called 1000,000 times then memory used still is 0 bytes
(1000,000 * 0 = 0), hence I still wonder when malloc(0) allocates 0 bytes
why system hanged by eating all memory ?



/* **** DO NOT TRY to run this code PLEASE ***. It will crash your
system. */
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char* p;

while(1)
{
p = malloc(0);

if(NULL == p)
{
printf("********* Out of Memory ******** \n");
break;
}
}

printf("---------------------\n");

return 0;
}
 

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

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top