Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Recovering from out of memory on the stack

Reply
Thread Tools

Recovering from out of memory on the stack

 
 
Walter Roberson
Guest
Posts: n/a
 
      01-10-2008
In article <fb6cee33-18ca-474f-b8a2->,
<> wrote:

>And just like you can malloc small amounts, you can also use up lots
>of stack memory by declaring huge arrays as local variables. There
>surely ought to be some way to recover if this fails.


C does not provide any such mechanism.

If you are declaring huge arrays as local variables such that
running out of stack memory is a serious problem that needs to be
potentially recoverable from, then Don't Do That: allocate just
a pointer variable in the local variables, and malloc() the required
memory, thus giving you control to detect not only -that- some
memory could not be allocated, but also control to detect -which-
memory could not be allocated.
--
We regret to announce that sub-millibarn resolution bio-hyperdimensional
plasmatic space polyimaging has been delayed until the release
of Windows Vista SP2.
 
Reply With Quote
 
 
 
 
gw7rib@aol.com
Guest
Posts: n/a
 
      01-10-2008
On 10 Jan, 20:27, sandysimon...@gmail.com wrote:
> I guess to rephrase what I'm asking... we tend to think of the stack
> being for small allocations and the heap for big ones. But it isn't
> always so.
>
> For example, I've seen some really paranoid code, where *every*
> malloc() is checked to see if it returned NULL, even if it's only for
> like 10 bytes to copy a string.


This is considered good practice.

> And just like you can malloc small amounts, you can also use up lots
> of stack memory by declaring huge arrays as local variables. There
> surely ought to be some way to recover if this fails.


If you need to get hold of some memory to use when malloc fails, then
one way to do this is to malloc some memory as a spare early on in the
program. Perhaps make your program bail out if this malloc fails. If
it doesn't, if the program then runs out of memory in the middle of
something interesting, you have some (so far unused) memory to play
with.

One problem might be if you run out of stack memory (assuming your
computer uses such a thing, which it probably does) as the stack is
used in the running of the program and you need the free memory to be
in a particular place, ie next to the rest of the stack. I can only
recommend that you use malloc rather than the stack for any "huge
arrays" you deal with, even if they are only local to a particular
function.

Hope that helps.
Paul.
 
Reply With Quote
 
 
 
 
Flash Gordon
Guest
Posts: n/a
 
      01-10-2008
jacob navia wrote, On 10/01/08 20:27:
> wrote:
>> Hi,
>>
>> I know that it's good practise to check the returned pointer from
>> malloc() against NULL when making large allocations on the heap, so as
>> to be able to attempt recovery in case of an out-of-memory error.
>>
>> But my question is: what about if you run out of memory while trying
>> to allocated things on the stack, e.g. a big local array variable? Is
>> there some way to hook in a function to run in these circumstances, to
>> be able to try to clean up?


<snip>

> This is an extremely difficult situation.
>
> Within the lcc-win compiler system, you can recover from such a
> situation if you use the try/catch feature, but it is VERY
> difficult since when you run into the recovery function
> there is almost no stack at all.


This, of course, is specific to lcc-win and not part of the C language.

<snip>

> You can have an idea of how much stack you are using if you do
> the following
>
> char *StartOfStack;
> int main(...)
> {
> char foo;
>
> StartOfStack = &foo;


Of course, if you do not call main recursively the compiler might decide
to allocate foo where it allocates "global" variables. I can see reasons
why this optimisation might make sense.

> }
>
> This will tell you approximately WHERE the stack begins.
>
> You can see how much you have used if in the function "fn" you do:
>
> int fn(void)
> {
> char foo;
> char *CurrentStack = &foo;
>
> size_t StackSize = CurrentStack - StartOfStack;


Of course, if the stack grows in the opposite direction (as it does on
the PowerPC) it could give very unexpected results. Not to mention on
embedded compilers which people have posted about as recently as this
week that do things like allocating *all* local variables statically.

> }
>
>
> You can then TEST before you call a function that uses a lot of stack
> if you are beyond some limit.


However you have no way of knowing (in general) what limit you need to
test against, so it does not help you.

> Of course this is very compiler specific too, but should work
> in most systems.


Apart from PowerPC and related processors (because you have the stack
direction wrong), so it won't work on big iron (or even relatively small
servers like those we run our accounts system on in my company) from IBM
or Apples from before they switched to x86 processors, or the afore
mentioned embedded compilers...

> P.S. When some people tell you that C "Doesn't use a stack" or
> that "C doesn't know about a stack" just ignore them, they
> are trying to confuse you.


No, they are trying to make a point that you still seem not to have
understood. Even with a stack your suggestion can easily fail miserably,
especially if you consider the linked list implementation of the C
semantics as being a stack.
--
Flash Gordon
 
Reply With Quote
 
Tor Rustad
Guest
Posts: n/a
 
      01-10-2008
David Tiktin wrote:

[...]

> A linked list can be used to implement a stack, as the implementation
> you describe undoubtedly did. The point remains that the semantics
> of C's function call and return describes a LIFO structure, known in
> CS circles as a stack. There are other ways to implement a stack,
> and the C Standard doesn't require any specific implementation. But
> IMHO, to say that a linked list which is being used in a FIFO manner
> is not a "stack" is not the best way to describe the situation


From the function call tree, translators may identify which function
life times are mutually exclusive, hence storage of object with
automatic storage duration, can be overlaid.

For implementations, using overlaid memory, is quite different from
using a stack.

--
Tor < | tr i-za-h a-z>
 
Reply With Quote
 
Tor Rustad
Guest
Posts: n/a
 
      01-10-2008
jacob navia wrote:

[...]

> P.S. When some people tell you that C "Doesn't use a stack" or
> that "C doesn't know about a stack" just ignore them, they
> are trying to confuse you.


Repeat after me... slowly 1000 times:

An C implementation may or may not, implement function calls using a stack.

--
Tor < | tr i-za-h a-z>
 
Reply With Quote
 
jameskuyper@verizon.net
Guest
Posts: n/a
 
      01-10-2008
David Tiktin wrote:
> On 10 Jan 2008, Lew Pitcher <> wrote:
>
> > On Jan 10, 2:05 pm, dj3va...@csclub.uwaterloo.ca.invalid wrote:
> >> In article
> >> <12ab019d-d4cb-44be-bdfb-35acea2cb...@j78g2000hsd.googlegroups.com
> >> >, Lew Pitcher <lpitc...@teksavvy.com> wrote:
> >>
> >> >On Jan 10, 1:31 pm, sandysimon...@gmail.com wrote:
> >> >> Hi,
> >>
> >> >> I know that it's good practise to check the returned pointer
> >> >> from malloc() against NULL when making large allocations on
> >> >> the heap, so as to be able to attempt recovery in case of an
> >> >> out-of-memory error.
> >>
> >> >> But my question is: what about if you run out of memory while
> >> >> trying to allocated things on the stack,
> >>
> >> >Repeat after me: "There is no stack in the definition of the C
> >> >Language"
> >>
> >> Not one described by that name, but it would be Rather Difficult
> >> to implement the semantics of function calls and automatic
> >> storage allocation without something that feels and smells like a
> >> stack.

> >
> > I know of at least one implementation that uses dynamic memory
> > allocations (i.e. allocations from the "heap", what ever that is)
> > to build function activation records. Each activation record
> > contains enough storage for all the function's automatic
> > variables, with each variable preallocated within the record. No
> > stack here; just a linked- list of memory blocks malloc()ed by the
> > underlying implementation.

>
> A linked list can be used to implement a stack, as the implementation
> you describe undoubtedly did. The point remains that the semantics
> of C's function call and return describes a LIFO structure, known in
> CS circles as a stack. There are other ways to implement a stack,
> and the C Standard doesn't require any specific implementation. But
> IMHO, to say that a linked list which is being used in a FIFO manner
> is not a "stack" is not the best way to describe the situation


That's a very abstract concept of a stack. A great many people have a
much more specific concept of a stack; the term occasionally used is
"hardware stack", and many of those people mistakenly believe that the
C standard requires a hardware stack. The concept they are thinking of
can be explained by considering the following code. That concept
implies that:
1. There is, or at least could be, a linear address space containing
the entire stack, which renders the pointer comparisons below
meaningful even though the C standard itself does not say so.
2. None of the calls to assert() in the following code will abort the
program.
3. Both calls to printf() will print the same thing.

#include <stdio.h>
#include <assert.h>
void f1(int *pa, int *pb, int *pc)
{
int d;
printf("%p\n", (void*)&d);
assert( (pa > pc) == (pc > &d) );
assert( (pa > pc) == (pb > pc) );
assert( (pa > &d) == (pb > &d) );
}

void f2(int *pa, int *pb)
{
int c;
f1(pa, pb, &c);
f1(pa, pb, &c);
}

int main(void)
{
int a,b;
f2(&a, &b);
return 0;
}

The statement "there is no stack in the definition of the C language"
is intended to remind people that any one of those calls to assert()
might fail, and that the two calls to printf() are not required to
produce the same output.
 
Reply With Quote
 
robertwessel2@yahoo.com
Guest
Posts: n/a
 
      01-10-2008
On Jan 10, 2:27*pm, sandysimon...@gmail.com wrote:
> Hi,
>
> I think this is a pretty silly reply - just think of "local variables"
> vs. "malloced memory" if you have hang-ups with the stack and the
> heap...
>
> I guess to rephrase what I'm asking... we tend to think of the stack
> being for small allocations and the heap for big ones. But it isn't
> always so.
>
> For example, I've seen some really paranoid code, where *every*
> malloc() is checked to see if it returned NULL, even if it's only for
> like 10 bytes to copy a string.
>
> This is pretty pointless, if the function checking malloc so carefully
> can't pick up the fact that it failed to allocate three local int
> variables say, taking up a whopping 12 bytes...



It's not pointless. Failing to check every malloc, or equivalent, is
simply an indication of a grievously flawed program. Now in some
sample or test code it's perhaps not unreasonable to omit, but
certainly nothing like that should ever make it into any kind of
production system. OTOH, the failure of most mallocs is simply a
fatal error, and it's quite reasonable to have a small wrapper around
malloc along the lines of:

void * mustmalloc(size_t s)
{
void *p;
p = malloc(s);
if (!p)
KaBoom(); /* issue diagnostic and abend */
return p;
}


> And just like you can malloc small amounts, you can also use up lots
> of stack memory by declaring huge arrays as local variables. There
> surely ought to be some way to recover if this fails.



If I fatally run out of stack space, I hope the implementation will
abend the program at that point. And most do.

It's relatively rare that a program can successfully recover from a
failing memory allocation. Even when a program does it, it's usually
only for a very limited portion of the allocations (for example,
storage allocated for buffering a large data file). In most cases
avoidance is a much better idea.

The thing you *don't* want to do is wander back into your program with
bad pointers, buffer overflows, and whatnot, which might cause all
sorts of havoc long after the failing memory allocation.

 
Reply With Quote
 
jacob navia
Guest
Posts: n/a
 
      01-10-2008
Tor Rustad wrote:
> jacob navia wrote:
>
> [...]
>
>> P.S. When some people tell you that C "Doesn't use a stack" or
>> that "C doesn't know about a stack" just ignore them, they
>> are trying to confuse you.

>
> Repeat after me... slowly 1000 times:
>
> An C implementation may or may not, implement function calls using a stack.
>


Who cares really?

I don't.

Most implementations use a stack, and in a discussion about stack
overflow your pedantic insistence is OFF TOPIC!

We are speaking about stack overflows here.

http://dictionary.reference.com/browse/pedant

pedant

–noun
1.a person who makes an excessive or inappropriate display of learning.
2.a person who overemphasizes rules or minor details.
3.a person who adheres rigidly to book knowledge without regard to
common sense.


--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
 
Reply With Quote
 
Walter Roberson
Guest
Posts: n/a
 
      01-10-2008
In article <fm69ol$mpf$>, jacob navia <> wrote:
>Tor Rustad wrote:


>> An C implementation may or may not, implement function calls using a stack.


>Most implementations use a stack, and in a discussion about stack
>overflow your pedantic insistence is OFF TOPIC!


It is not off-topic when it is in direct response to your claim
in this very subthread, that,

>>>P.S. When some people tell you that C "Doesn't use a stack" or
>>>that "C doesn't know about a stack" just ignore them, they
>>>are trying to confuse you.


--
We regret to announce that sub-millibarn resolution bio-hyperdimensional
plasmatic space polyimaging has been delayed until the release
of Windows Vista SP2.
 
Reply With Quote
 
sandysimons53@gmail.com
Guest
Posts: n/a
 
      01-10-2008
Interesting.

I know that the stack grows down from the high addresses while the
heap grows up the address space - I wonder if it would be possible to
have a #pragma or something similar that would tell the compiler "Hey
I've got some very big local arrays, so I'm gonna need plenty of stack
space - try to allow more room than usual for the stack at the expense
of the heap"? That might help avoid stack overflows.

Or maybe the compiler could provide a global variable like
__min_stack_address that would let you use the trick you described and
be able to tell how far off you were from hitting the stack limit.

~ Sandy


jacob navia wrote:
> wrote:
> > Hi,
> >
> > I know that it's good practise to check the returned pointer from
> > malloc() against NULL when making large allocations on the heap, so as
> > to be able to attempt recovery in case of an out-of-memory error.
> >
> > But my question is: what about if you run out of memory while trying
> > to allocated things on the stack, e.g. a big local array variable? Is
> > there some way to hook in a function to run in these circumstances, to
> > be able to try to clean up?
> >
> > Thanks for any insight.
> >
> > ~ Sandy

>
> This is an extremely difficult situation.
>
> Within the lcc-win compiler system, you can recover from such a
> situation if you use the try/catch feature, but it is VERY
> difficult since when you run into the recovery function
> there is almost no stack at all.
>
> Detailed instructions for lcc-win can be found in the
> tutorial. Look t the chapter about structured
> exception handling.
>
> In other compilers, the situation is worst. This is
> very system specific, and depends on the facilities that
> offers the compiler system in question. Besides, you can change
> the size of the stack under windows: this can be changed with
> a compiler option.
>
> Under Unix you have to change the limits of the user probably
> but better look at the documentation.
>
> You can have an idea of how much stack you are using if you do
> the following
>
> char *StartOfStack;
> int main(...)
> {
> char foo;
>
> StartOfStack = &foo;
> }
>
>
> This will tell you approximately WHERE the stack begins.
>
> You can see how much you have used if in the function "fn" you do:
>
> int fn(void)
> {
> char foo;
> char *CurrentStack = &foo;
>
> size_t StackSize = CurrentStack - StartOfStack;
> }
>
>
> You can then TEST before you call a function that uses a lot of stack
> if you are beyond some limit.
>
> Of course this is very compiler specific too, but should work
> in most systems.
>
> P.S. When some people tell you that C "Doesn't use a stack" or
> that "C doesn't know about a stack" just ignore them, they
> are trying to confuse you.
>
>
> --
> jacob navia
> jacob at jacob point remcomp point fr
> logiciels/informatique
> http://www.cs.virginia.edu/~lcc-win32

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
C/C++ compilers have one stack for local variables and return addresses and then another stack for array allocations on the stack. Casey Hawthorne C Programming 3 11-01-2009 08:23 PM
Recovering Memory Card Data Davy Digital Photography 1 09-10-2007 08:19 PM
Recovering Memory Collins Computer Support 6 06-01-2006 10:52 PM
Out Of Memory Error and Stack Size karthikeyan.jambulingam@gmail.com Java 11 02-17-2006 03:05 PM
JVM thread stack (out of memory) Chenxi Java 2 11-30-2005 12:36 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57