If malloc fails

J

Jens.Toerring

brian said:
If the implementation follows the standards, the above is what I get
(that ENOMEN is set) from the malloc() man page in openBSD. However,
in the man page in linux, there was no mention of ENOMEM being set,
and I couldn't get malloc() to fail in linux even using setrlimit().

See the NOTES section of the Linux man page, it's mentioned there.
Regarding your problem to get malloc() to fail lets discuss this in
comp.os.linux.development.apps, you can definitely get it to fail.
Now, you have to test for how much the implementation follows any
standard and what standards are followed, which makes portability a pain.
And per the scope of this newsgroup, any extension of ISO C is off
topic. So if the C standard does not require malloc() to set errno,
then we have serious problems when testing for errors. We first
have to determine what standard is followed. We then have to re-write
our error code by implementation or use a lot of #ifndef #if . . .

I don't see why having errno set or not would be a problem at all -
just assume it won't get set and everything should be fine. There
isn't any additional information you get from checking errno you
don't already have when malloc() returns NULL.

Regards, Jens
 
K

Keith Thompson

Malcolm said:
The problem is that if the system won't give you a hundred bytes for a file
name, will it give you the memory it needs to call fopen() or the save file
dialog?

So pre-allocate enough memory to do whatever cleanup is necessary.

One possible approach (I haven't tried this, so undoubtedly large
holes could be shot in the idea) might be to malloc() a medium-sized
chunk of memory during startup, maybe a few kilobytes. If a malloc()
fails, invoke a cleanup routine that first free()s this initial chunk,
providing enough free space to continue the cleanup before bailing out.

There's no guarantee that this would work.
Once you are totally out of heap then you are in trouble, unless the system
has been specifically written so that it can function without heap memory.
Anyway, say your program has 10MB of memory available. Given that the
program will run out of memory on a run, the chance of hundred byte
allocation being the one to straddle the boundary is 1 in a hundred
thousand. So if it's a text editor, taking several minutes to run, even if
it runs out of memory on every run, the computer is much more likely to
break than it is to execute your malloc() failure handling code. So no, we
don't need to bother too much what goes into that code.

I'd rather handle the error properly than gamble on the assumption
that it's unlikely.
 
B

brian

> See the NOTES section of the Linux man page, it's mentioned there.
> Regarding your problem to get malloc() to fail lets discuss this in
> comp.os.linux.development.apps, you can definitely get it to fail.


I left off the headers and main() on the code below to focus on just the
code used to set up the constraint and the attempt to break it.

The method I used to attempt to get malloc to fail was:

char *ch = NULL;

struct rlimit r;
r.rlim_cur = 32;
r.rlim_max = 32;

/* sets the constraint on RLIMIT_DATA to 32 bytes */

if ( ( setrlimit(RLIMIT_DATA, &r) ) == -1 ) {
perror("setrlimit() error\n");
exit(EXIT_FAILURE);
}

/* attempts to allocate 4 * 64 bytes */

if ( (ch = malloc( sizeof(long) * 64) ) == NULL) {
perror("malloc() failed\n");
exit(EXIT_FAILURE);
}

free(ch);

Now, per the man page in linux for setrlimit, RLIMIT_DATA
should define the constraints on malloc() and related functions. Now,
the definition for RLIMIT_DATA is slightly different in BSD.

The biggest question is how memory is handled by the kernel. And
that is where I left the problem of trying to make malloc() fail in
linux. I haven't dug into virtual memory yet.

If I doubt malloc() will set errno, then I do not want
to use perror(). An assert() might work better.
> I don't see why having errno set or not would be a problem at all -
> just assume it won't get set and everything should be fine. There
> isn't any additional information you get from checking errno you
> don't already have when malloc() returns NULL.
>
> Regards, Jens


True. But when you write your error code, you want to know whether
you want to print the STDERR stream or not. If I know that malloc()
will not set errno under different implementations, then I can just
check for NULL, write a printf() and exit().

The only applicable question to comp.lang.c is how to write error code
that is portable for malloc() and it's related functions. Of course,
setrlimit() is not defined by ISO C99.

Brian

P.S. Do you want me to cross post this response?
 
B

brian

Fine. But please take this to comp.os.linux.development.apps where
it is on-topic. Standard C doesn't have a setrlimit() function.

I have already discussed this in comp.unix.programmer. But the op
question was how to write error code and exit code for malloc().
The answer is part implementation specific and part C99 specific.
And I said in my response that setrlimit() is off topic here.
Well, you're absolutely safe if you don't care if malloc() sets errno
or not and just check the return value for NULL. The C standard does
not require malloc() to set errno, so don't rely on it and there are
are no portability problems at all. I really can't see your problem.

If you don't care about errno, there is no portability problem If you
do, there might be a portability problem. Of course, you should test
your code to make sure the error code and/or exit code will be executed.

Brian
 
J

Jens.Toerring

brian said:
I left off the headers and main() on the code below to focus on just the
code used to set up the constraint and the attempt to break it.
The method I used to attempt to get malloc to fail was:

Fine. But please take this to comp.os.linux.development.apps where
it is on-topic. Standard C doesn't have a setrlimit() function.
True. But when you write your error code, you want to know whether
you want to print the STDERR stream or not. If I know that malloc()
will not set errno under different implementations, then I can just
check for NULL, write a printf() and exit().

Well, you're absolutely safe if you don't care if malloc() sets errno
or not and just check the return value for NULL. The C standard does
not require malloc() to set errno, so don't rely on it and there are
are no portability problems at all. I really can't see your problem.

Regards, Jens
 
M

Malcolm

Keith Thompson said:
So pre-allocate enough memory to do whatever cleanup is necessary.

One possible approach (I haven't tried this, so undoubtedly large
holes could be shot in the idea) might be to malloc() a medium-sized
chunk of memory during startup, maybe a few kilobytes. If a malloc()
fails, invoke a cleanup routine that first free()s this initial chunk,
providing enough free space to continue the cleanup before bailing out.

There's no guarantee that this would work.
This is the sort of thing you've got to do. If fopen() calls malloc()
internally, for example, you have to either write your own file routine that
uses a static area of memory, or free enough memory (and know that it won't
be grabbed by another process). So the whole thing is rather tricky and
difficult.
I'd rather handle the error properly than gamble on the assumption
that it's unlikely.
You've got to decide how to allocate programming resources. If you're
writing control systems for a nuclear power station, or even a text editor
for Microsoft, then it is probable that development costs don't matter. If
you're writing a video game then costs, and, even more so, time really does
matter.
Now if you are allocating a 100 bytes on a 10MB system, and memory is being
allocated in a lot of smallish chunks at random, and your program runs out
of memory, then the chnace that it will run out of memory during the 100
byte allocation is 1 in 100000.
Let's suppose the computer runs out of memory every ten minutes, or 150
times a day. That means you can run for 666 days, or about two years,
before the code will be ever executed. It is unlikely that a desktop
computer can run for two years continuously without some sort of mechanical
failure. There will also be software failures - my copy of Windows certainly
can't run for two years without crashing.
Then you've got the problem that you need some sort of fancy memory scheme
to cope with having no core left anyway. The whole idea of handling the
error suddenly seems a lot less attractive.
 
P

Paul Hsieh

I'll go with the "it depends answers" that others have posted.
Fundamentally you have to decide on an error policy for your program,
then just follow it.
It depends what you are allocating. If you are allocating a few bytes, maybe
for a filename, on a large system then basically malloc() cannot fail.

What? There is no way you can predict the size of the straw that
breaks the camel's back. This is also a system/platform assumption
that is quite possibly incorrect. Certain "poor heap architectures"
such as the one used in the original UNIX platform (and which
apparently SCO still uses) can accumlate "lost blocks" -- meaning that
any successive random sequence of allocations regardless of size will
eventually exhaust the heap. Another possibility is that in a
multi-process system you are unable to move the sbrk() pointer because
some application has grabbed the system memory allocation lock in some
way.
[...] The system will have issued "low on memory" warnings long before this
happens.

Huh? My (cheapo) system doesn't do that.
However for the program to be correct, you still need to handle the failure.
Exit is perfectly reasonable.

How do you know this? If the function is its own culprit, but it
strictly observes error codes, then freeing its resources and simply
returning with an error code may be sufficient to completely recover
the main program, simply with no valid result from the leaf function.

For example, if you are writing a bignum math calculator on a 32 bit
system, and an end user asks it to perform Factorial(100663296), its
likely to run out of memory in the process of trying to compute this.
If you simply free the memory used and issue some kind of error
message, it can continue with other computations without exiting
(which could be tragic, if there was a long sequence of unsaved work
for example.)
 

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

No members online now.

Forum statistics

Threads
474,145
Messages
2,570,826
Members
47,372
Latest member
LucretiaFo

Latest Threads

Top