How to make malloc() fail ?

H

Harald van =?UTF-8?B?RMSzaw==?=

Army1987 said:
Even if size_t is an unsigned type other than unsigned int,
malloc((size_t)(-1)) does the same as malloc(SIZE_MAX). So I don't think
he meant size_t needn't be the type unsigned int, or the mention
of that macro would be irrelevant.

I initially read it as

where it makes sense, but now re-reading it, I think you and Flash Gordon
may be right.
 
U

user923005

Many modern workstations have 4 Gb or more of memory installed.


That's why it's not possible within ISO C to cause malloc to reliably
fail.

#include <stdio.h>
#include <stdlib.h>
/*
I would be keen to know about the implementation
where this code does not cause malloc() to fail.
P.S.:
It ain't a leak. It's a river.
*/
int main(void)
{
char *p;
for (;;) {
p = malloc((size_t) - 1);
if (p == 0) {
puts("I made malloc() fail.");
exit(EXIT_SUCCESS);
}
}
return 0;
}

However you can use support code to simulate memory allocation
failures. The support code can be portable C.

I think you're a bit off here.
 
S

santosh

user923005 said:
#include <stdio.h>
#include <stdlib.h>
/*
I would be keen to know about the implementation
where this code does not cause malloc() to fail.
P.S.:
It ain't a leak. It's a river.
*/
int main(void)
{
char *p;
for (;;) {
p = malloc((size_t) - 1);
if (p == 0) {
puts("I made malloc() fail.");
exit(EXIT_SUCCESS);
}
}
return 0;
}

You're right, thanks.
 
B

Ben Pfaff

user923005 said:
/*
I would be keen to know about the implementation
where this code does not cause malloc() to fail.
P.S.:
It ain't a leak. It's a river.
*/
int main(void)
{
char *p;
for (;;) {
p = malloc((size_t) - 1);
if (p == 0) {
puts("I made malloc() fail.");
exit(EXIT_SUCCESS);
}
}
return 0;
}

This will make malloc fail on all implementations I am aware of.
However, it doesn't actually have the effect that I'd want for
testing. For testing purposes, I want to make the next call to
malloc fail, or perhaps to make all future calls to malloc fail.
But I'd expect that on many implementations, code similar to the
above would typically call malloc(-1) once, which would fail
without actually allocating any memory, and then future calls to
malloc would succeed or fail in the same way as if I hadn't
called malloc(-1) at all.
 
R

Richard Heathfield

Ben Pfaff said:

For testing purposes, I want to make the next call to
malloc fail, or perhaps to make all future calls to malloc fail.
But I'd expect that on many implementations, code similar to the
above would typically call malloc(-1) once, which would fail
without actually allocating any memory, and then future calls to
malloc would succeed or fail in the same way as if I hadn't
called malloc(-1) at all.

What I do is arrange that, in D allocations from now, the next U
allocations will fail if they exceed B bytes. (Of course, they may fail
anyway, but I can't do anything about that.)

This can be done portably.

It's quite handy because it means that you can test the handling of
failures of "inner" allocs in ADT code - the "delay" facility allows
you to hop around the outer allocation of the metastructure and instead
put stress on the code that allocates memory for the containment of
whatever information it is that you're encapsulating.
 
B

Ben Pfaff

Richard Heathfield said:
What I do is arrange that, in D allocations from now, the next U
allocations will fail if they exceed B bytes. (Of course, they may fail
anyway, but I can't do anything about that.)

This can be done portably.

Please, tell us how. I have always done so by using a malloc
wrapper that does what I want. Not having to do that would be
convenient sometimes.
 
R

Richard Heathfield

Ben Pfaff said:
Please, tell us how.

Sorry to be so vague about this. Will it suffice to say that I use a
wrapper? If this disappoints you, I'm sorry, although of course the
wrapper is switchable-offable. I don't want to go into any more detail
than that in clc, at least not for the time being.
 
U

user923005

This will make malloc fail on all implementations I am aware of.
However, it doesn't actually have the effect that I'd want for
testing. For testing purposes, I want to make the next call to
malloc fail, or perhaps to make all future calls to malloc fail.
But I'd expect that on many implementations, code similar to the
above would typically call malloc(-1) once, which would fail
without actually allocating any memory, and then future calls to
malloc would succeed or fail in the same way as if I hadn't
called malloc(-1) at all.

For that I use a binary search to allocate the largest possible
remaining block after the first failure.
 
B

Ben Pfaff

user923005 said:
For that I use a binary search to allocate the largest possible
remaining block after the first failure.

Which won't help with implementations of malloc that allocate
memory in pools of equal-sized blocks: it's quite possible in
such an implementation to allocate 4 blocks of 16 bytes each,
even if you can't allocate a single block of 64 bytes;
conversely, you might be able to allocate one block of 64 bytes
but not one block of 16 bytes.

But I bet your approach works most of the time.
 
U

user923005

Which won't help with implementations of malloc that allocate
memory in pools of equal-sized blocks: it's quite possible in
such an implementation to allocate 4 blocks of 16 bytes each,
even if you can't allocate a single block of 64 bytes;
conversely, you might be able to allocate one block of 64 bytes
but not one block of 16 bytes.

But I bet your approach works most of the time.

For really cantankerous implementations you could have a loop that
allocates one byte at a time (until that fails) after the bsearch
block allocation.
 
B

Ben Pfaff

user923005 said:
For really cantankerous implementations you could have a loop that
allocates one byte at a time (until that fails) after the bsearch
block allocation.

That wouldn't help on the implementation I'm describing, because
it would only exhaust the pool for 1-byte allocations. There
could still be some room in pools for larger allocations.

Perhaps I can make the situation more concrete by referring you
to a very simple allocator that works this way, the file malloc.c
at:
http://www.stanford.edu/class/cs140/pintos/pintos/src/threads/
It is not an ISO C compliant malloc, nor is it written in
strictly conforming ISO C, but it illustrates the principle at
work.
 
U

user923005

That wouldn't help on the implementation I'm describing, because
it would only exhaust the pool for 1-byte allocations. There
could still be some room in pools for larger allocations.

Perhaps I can make the situation more concrete by referring you
to a very simple allocator that works this way, the file malloc.c
at:
http://www.stanford.edu/class/cs140/pintos/pintos/src/threads/
It is not an ISO C compliant malloc, nor is it written in
strictly conforming ISO C, but it illustrates the principle at
work.

Maybe a custom solution like this then:

#include <stdlib.h>
void exhaust_bens_memory()
{
size_t blocksize = 2048;
while (blocksize) {
while (malloc(blocksize)) {;}
blocksize >>= 1;
}
}
 
C

crox

it is really platform specific, for example in my system libc, malloc
has this implemetation:

....
/* why would you ever want a negative malloc, this would mean */
/* a very large positive number which can't be filled */

if ((int)nbytes < 0){
errno = ENOMEM;
return NULL;
}

....
so calling `malloc()' with negative argument will cause it to fall.
 
R

Richard Tobin

crox said:
it is really platform specific, for example in my system libc, malloc
has this implemetation:

...
/* why would you ever want a negative malloc, this would mean */
/* a very large positive number which can't be filled */

if ((int)nbytes < 0){

The argument to malloc() has type size_t, which is unsigned, so you
*can't* pass it a negative value. It may well be true that values
corresponding to negative ints are usually the result of a bug in the
program causing a negative value to be converted to a large size_t,
but I'm not sure why your code bothers to make this check, since if
requests for "very large" amounts of memory can't be filled, it will
fail anyway without the check.

I think the comment would be more accurate if it read "Why would you
ever want to malloc such a huge amount? It can't be done and is more
likely an erroneous attempt to malloc a negative size".

-- Richard
 
W

William Hughes

Ben Pfaff said:



Sorry to be so vague about this. Will it suffice to say that I use a
wrapper?



How?


Assume that you have a program in which malloc is not wrappred.
How do you wrap it without going through and replacing all the calls
to
malloc? Sure

#define malloc wrap_malloc

will probably work, but you can't redefine a library function in
portable code.


(given that you have a wrapper function things are straightforward.
Store state as a global or pseudo-global (static in a module),
manipulate with wrap_malloc_change_state()
then the wrapper function will return NULL (fail) or call
malloc, depending on the state)


- William Hughes
 
U

user923005

The argument to malloc() has type size_t, which is unsigned, so you
*can't* pass it a negative value. It may well be true that values
corresponding to negative ints are usually the result of a bug in the
program causing a negative value to be converted to a large size_t,
but I'm not sure why your code bothers to make this check, since if
requests for "very large" amounts of memory can't be filled, it will
fail anyway without the check.

I think the comment would be more accurate if it read "Why would you
ever want to malloc such a huge amount? It can't be done and is more
likely an erroneous attempt to malloc a negative size".

If the chip can address it, and if I have that much available, I would
be rather put out if the malloc() function arbitrarily decided not to
give it to me.
That little snippet of code is by a programmer trying to be more
clever than he ought to be.
IMO-YMMV.
 
R

REH

This is regarding to test an SDK memory stuff.
In what situation malloc gets fail.
any comment/reply pls....
regards

If you just wish to test your error paths, you don't really need to
make malloc fail, just make your program think that it did:

#if TESTING

/* function to determine if malloc should fail */
int malloc_should_fail(void);

#define malloc(S) (malloc_should_fail() ? NULL : (malloc)(S))

#endif

I don't believe it is portable to override malloc with a macro, but
its only for testing purposes, not your release builds.
 
R

Richard Tobin

[/QUOTE]
If the chip can address it, and if I have that much available, I would
be rather put out if the malloc() function arbitrarily decided not to
give it to me.

I assume from the comment that it isn't available. It's not unusual
for half the address space to be used for kernel memory. Of course,
if size_t is 64 bits, there's no prospect of more than half of it being
available anyway in the foreseeable future.

-- Richard
 

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

Alternative to Malloc in C 0
How to make extension 1
How to make portfolio 0
malloc 40
Malloc question 9
How do I make this craftinfsystem Work 1
How to make online editor? 0
Malloc Query 86

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,135
Latest member
VeronaShap
Top