static, global variable memory allocation

F

Flash Gordon

Nishu wrote, On 07/02/07 11:12:
You may be right about static/global allocation.

The OP asked about variables declared static in functions, globals, and
automatic variables, so that is what I focused on.
> It is placed in zero-
initialized region which can be defined in any part of memory(but
rarely(or never?) on memory which is stack) but,

I stated it could be not that it is on any current system. Others stated
that it was declared on the heap, which depending on the definition of
heap I would dispute, and one person at least agreed I had a point.
> AFAIK, dynamic memory
allocations are termed as heap which must be freed before execution
gets over. (i.e, alloc/malloc/realloc)

If that is your definition of heap then by definition *alloc/free use a
heap ;-)

Actually, my usage of the word heap corresponds with yours which is why
I said that static/global data is not stored on the heap in my
experience. However, I can conceive of a system effectively using
malloc/calloc to allocate space for statics/globals before calling main,
just as I can conceive of the space being allocated on a stack calling main.
 
C

Charlton Wilbur

ES> And the bigger issue: If you faced and aced a string of
ES> such questions in an interview and were offered the job, would
ES> you take it? Or would you flee?

I have, and I fled.

Charlton
 
E

Eric Sosman

Nishu said:
I don't see any other alternatives rather than register/stack
allocation for local variables. I would be happy to know alternative
implementations for it.

One alternative arises from the fact that "the stack" can
be implemented in different ways. Nowadays it is common to use
sequential allocation: You reserve a special array somewhere,
initialize a pointer to point to one end of it, and let the
pointer wander up and down in the array as functions come and
go. Pretty simple design, and pretty cheap.

But it's not the only way, and not necessarily the "best"
way in all circumstances. One problem is that you either need
to guess how much stack space you'll need before starting the
program (this is probably equivalent to the Halting Problem)
or else come up with extra mechanisms to detect stack overflow
and make adjustments. Sometimes this isn't too bad, but if
memory is scarce or if you have a lot of stacks (multi-threaded
program) there can be difficulties.

So, another way is to allocate "stack frames" from a source
similar to what malloc() uses, and to chain them together in a
linked list. A stack built this way need not be contiguous, so
you need not reserve a contiguous chunk of memory to hold it
and you need not worry about exhausting that contiguous chunk.
A particular memory area could be a stack frame at one moment,
then be claimed by malloc() and released by free(), and then
wind up as part of an entirely different stack. Perhaps someone
with IBM zSeries (S/390) experience can say whether C on that
machine uses this sort of strategy; its ancestor the S/360 did
not have a "stack pointer register" nor stack-oriented call and
return instructions.

There could also be a mixed-mode strategy: Allocate a small
sequential stack to begin with, and when it overflows expand it
by allocating and linking in a fresh "super-frame." Such a
stack would be "locally contiguous" but "globally discontiguous."
I haven't heard of anyone using this approach, but it might make
sense in some circumstances.
 
S

santosh

Keith said:
Richard Heathfield said:
The memory allocated by malloc (if any) is taken from the free
store, for which the term "heap" may or may not be applicable on any
particular platform. Note also that m is not freed. What is freed is
the memory (if any) that was allocated by malloc.
[...]

That raises an interesting question about the word "heap".

The words "stack" and "heap" occur nowhere in the C standard. It's
(too) common to refer to the area used to allocate automatic objects
as the "stack", but I think most of us agree that this is misleading
and incorrect.

Can a perverse but conforming implementation use the "heap" for
automatic objects. As long as their properties, as dictated by the
standard, are honoured, I don't see why they should be allocated from
a stack.
The word "stack", in this context, implies a
CPU-specific region of memory that grows linearly in one direction,
controlled by a "stack pointer" that is typically (but not always) a
dedicated CPU register.

I may be wrong, but it was my impression that a stack is simply a LIFO
data structure. It doesn't have to have any specific hardware support.
On stackless architectures, a LIFO may have to be simulated by the C
implementation, for auto objects.
Clearly there are C implementations that
don't use this mechanism. On the other hand, automatic objects are
certainly allocated and deallocated in a stack-like (last-in
first-out) manner, so in that sense, the term "stack" might be
appropriate. But the CPU-specific meaning is so strong that this is
misleading, at least when we're talking about the requirements of the
C language rather than the details of a particular implementation.

Yes. It curious why so many students of C are bursting to know where C
objects are stored. I would've thought that an assembly language or
machine architecture course would be the proper place to recieve such
information.
The word "heap" on the other hand, doesn't seem to carry the same kind
of semantic baggage. In my understanding, the term "heap" refers to a
region of memory used for dynamic allocation (malloc/free, new/delete,
or whatever);

In many architectures the same memory is used for both the stack and
the heap. The former typically grows down from the high end of the
address space, while the latter grows in the opposite direction.

there is at most a weak impliciation that it's
contiguous.

I don't think so. For example in x86's segmented memory model, we can
have multiple heaps which are not contiguous. Even multiple objects
needn't be contiguous with one another.
Though the standard doesn't use the word "heap", I'm
beginning to think that it's reasonable to use that word informally to
refer to the <whatever> from which malloc() allocates memory, and to
which free() returns it. In other word's I see the word "heap" as
having just the right level of vagueness to describe the general
underlying mechanism used by malloc and free.

Yes, it could be used, atleast for the lack of a better term, which
would be both concise and easily understood. CBFalconer recently used
the term "memory arena". I wonder how appropriate that is?
Are there any real-world systems (with C implementations supporting
malloc() and free()) for which the term "heap" would be inappropriate?
If so, what and why? Are there even any *theoretical* systems for
which the term "heap" would be in appropriate; if so, why?

Many embedded devices like the PIC and other chips often don't have
access to the main system memory. Presumably, implementations for such
systems might forego *alloc() and free() and hence "heap" would be
irrelevant.
 
K

Keith Thompson

santosh said:
Keith Thompson wrote: [...]
That raises an interesting question about the word "heap".

The words "stack" and "heap" occur nowhere in the C standard. It's
(too) common to refer to the area used to allocate automatic objects
as the "stack", but I think most of us agree that this is misleading
and incorrect.

Can a perverse but conforming implementation use the "heap" for
automatic objects. As long as their properties, as dictated by the
standard, are honoured, I don't see why they should be allocated from
a stack.

Sure. It's not even necessarily perverse; I think that some IBM
mainframe systems do this.
I may be wrong, but it was my impression that a stack is simply a LIFO
data structure. It doesn't have to have any specific hardware support.
On stackless architectures, a LIFO may have to be simulated by the C
implementation, for auto objects.

From a computer science point of view, yes, a "stack" is simply a LIFO
data structure, which can be implemented in any number of ways
(contiguous array, linked list, etc.). But if you're talking about a
specific CPU architecture, the phrase "the stack" typically refers to
the CPU-specific structure I described above. If someone says that
automatic variables are allocated on "the stack", that tends to imply
the CPU-specific structure -- at least, it does to me.
Yes. It curious why so many students of C are bursting to know where C
objects are stored. I would've thought that an assembly language or
machine architecture course would be the proper place to recieve such
information.

Sure, but knowing something about the underlying architecture can be
helpful in understanding *why* C defines things the way it does.
Though the standard doesn't use the word "stack", the way automatic
objects are allocated and deallocated is almost certainly motivated in
part by the kind of CPU-specific stack implementation described above.
If you have this kind of system stack, meeting the standard's
requirements for automatic objects is straightforward. If you don't,
you have to go to some extra effor to "fake it". The danger is
assuming that "all the world's a <whatever>".

By contrast, consider the way Perl works. Much of Perl's syntax is
borrowed from C, and it has functions and things that look, and
*usually* act, very much like C automatic objects. But they're not
necessarily allocated and deallocated in a stack-like manner. For
example, the equivalent of:

int *create_new_int(void)
{
int local;
return &local; /* BAD! */
}

actually works in Perl; the object isn't deallocated on exit from the
function as long as anything refers to it. In effect, everything is
heap-allocated and garbage-collected. Some knowledge of CPU
architecture is helpful in understanding *why* C doesn't work this
way.
In many architectures the same memory is used for both the stack and
the heap. The former typically grows down from the high end of the
address space, while the latter grows in the opposite direction.

Ok. In that case, I'd say that "the heap" could refer to the region
of memory currently allocated for management by malloc and free; this
region may grow or shrink over time (in, ironically enough, a
stack-like manner).
I don't think so. For example in x86's segmented memory model, we can
have multiple heaps which are not contiguous. Even multiple objects
needn't be contiguous with one another.

Then that's an argument *against* talking about "the heap" in general.
I was speculating that, unlike the phrase "the stack", the phrase "the
heap" might be generic enough to refer to the malloc/free mechanism of
any possible C implementation. But if some such implementations have
multiple things they call "heaps", then "the heap" becomes ambiguous
and/or misleading.

[...]
 
G

Gordon Burditt

That raises an interesting question about the word "heap".
Can a perverse but conforming implementation use the "heap" for
automatic objects.

I'm not so sure it would be that perverse. OS/360 linkage conventions
used a linked list of save areas instead of a stack. The save area
could be allocated in static storage (if the function is guaranteed
not to be re-entered), or it could be obtained with GETMAIN (the
system call likely to be used by malloc() to obtain storage from
the system).

A C compiler would have to assume that a C function COULD BE called
directly or indirectly from itself unless it could prove that it
wasn't. Functions that didn't call any other functions could
dispense with allocating a save area at all. Extending the save
area could provide space for auto variables. Dealing with
variable-length arrays might get a little tricky.

Now, when I was using this, C didn't exist. Other languages like
PL/1 and Pascal did. Pascal has a more complex setup than C (the
equivalent of an "auto" variable in an outer function can be referred
to in an inner function, even in the presence of recursion). There's
no reason C couldn't use this technique.
As long as their properties, as dictated by the
standard, are honoured, I don't see why they should be allocated from
a stack.


I may be wrong, but it was my impression that a stack is simply a LIFO
data structure. It doesn't have to have any specific hardware support.
On stackless architectures, a LIFO may have to be simulated by the C
implementation, for auto objects.

You need some rough equivalent to a "stack pointer" regardless.
Something has to let you find the last-in objects and keep track
of how much is on the LIFO. It might be a pointer or a counter or
something else. It's likely to be put in a CPU hardware register
(if there are any) even if there are no "PUSH" or "POP" instructions
or auto-increment/auto-decrement addressing modes to directly provide
a stack.
Yes. It curious why so many students of C are bursting to know where C
objects are stored. I would've thought that an assembly language or
machine architecture course would be the proper place to recieve such
information.

The answer seems to be: homework.

I prefer to think of it as "that place from which malloc() obtains
its storage", which doesn't rule out the possibility that there is
only one place from which memory is allocated, all intermixed.

In many architectures the same memory is used for both the stack and
the heap. The former typically grows down from the high end of the
address space, while the latter grows in the opposite direction.

Contrary to popular assumptions, the stack (if there is one) does
not always grow north.
I don't think so. For example in x86's segmented memory model, we can
have multiple heaps which are not contiguous. Even multiple objects
needn't be contiguous with one another.


Yes, it could be used, atleast for the lack of a better term, which
would be both concise and easily understood. CBFalconer recently used
the term "memory arena". I wonder how appropriate that is?

I *DEFINE* "heap" as "that place from which malloc() obtains its
storage", and unless you're going to argue that in some implementation
there is no such place, but malloc() still works, it's hard to see
where it would be inappropriate.

I've pretty much defined this problem out of existence.
 
C

Christopher Layne

Flash said:
If that is your definition of heap then by definition *alloc/free use a
heap ;-)

Actually, my usage of the word heap corresponds with yours which is why
I said that static/global data is not stored on the heap in my
experience. However, I can conceive of a system effectively using
malloc/calloc to allocate space for statics/globals before calling main,
just as I can conceive of the space being allocated on a stack calling main.

Also, a non-standard function, but alloca() goes against the grain of all this
as well.
 
D

Dave Vandervies

In many architectures the same memory is used for both the stack and
the heap. The former typically grows down from the high end of the
address space, while the latter grows in the opposite direction.

Contrary to popular assumptions, the stack (if there is one) does
not always grow north.[/QUOTE]

If there is a stack[1], then the direction in which it grows is trivially
reducible to a Simple Matter Of orienting your system appropriately.


dave

[1] In this context, "stack" refers to something known to grow
unidirectionally. In contexts where this can not be assumed, the
direction in which it grows is a rather less simple matter.
 
N

Nishu

One alternative arises from the fact that "the stack" can
be implemented in different ways. Nowadays it is common to use
sequential allocation: You reserve a special array somewhere,
initialize a pointer to point to one end of it, and let the
pointer wander up and down in the array as functions come and
go. Pretty simple design, and pretty cheap.

Yes, It is common. Systems can either have Top-down or bottom-up
approach for this kind of implementation. Top down approach is
preferred implementation for stack. We can have sequential memory(A
very big array) whose one end is used to allocate heap and other end
is used as stack (say decrementing stack) and we have an idea how much
is the system's maximum (stack + heap) requirement, so stack overflow
is somewhat avoided.
So, another way is to allocate "stack frames" from a source
similar to what malloc() uses, and to chain them together in a
linked list. A stack built this way need not be contiguous, so
you need not reserve a contiguous chunk of memory to hold it
and you need not worry about exhausting that contiguous chunk.
A particular memory area could be a stack frame at one moment,
then be claimed by malloc() and released by free(), and then
wind up as part of an entirely different stack. Perhaps someone
with IBM zSeries (S/390) experience can say whether C on that
machine uses this sort of strategy; its ancestor the S/360 did
not have a "stack pointer register" nor stack-oriented call and
return instructions.

There could also be a mixed-mode strategy: Allocate a small
sequential stack to begin with, and when it overflows expand it
by allocating and linking in a fresh "super-frame." Such a
stack would be "locally contiguous" but "globally discontiguous."
I haven't heard of anyone using this approach, but it might make
sense in some circumstances.

This is interesting.
Thanks,
Nishu
 
K

Keith Thompson

Nishu said:
Yes, It is common. Systems can either have Top-down or bottom-up
approach for this kind of implementation. Top down approach is
preferred implementation for stack.
[...]

There is no reason (as far as standard C is concerned) to prefer a
top-down stack over a bottom-up stack. (There may be CPU-specific
reasons.)
 
N

Nishu

Can a perverse but conforming implementation use the "heap" for
automatic objects. As long as their properties, as dictated by the
standard, are honoured, I don't see why they should be allocated from
a stack.

IMO, stack suits the requirement of auto variables at best. As soon a
leaf function is called from parent function, stack is used to store
the status of registers, passing arguments, etc and this scope is
defined till the control stays in leaf function. Similar is the case
with auto/local variables of leaf function. Scope is defined till the
control is in leaf function.

You have to free (to tell system that you can re-write it) "Heap"
every time, you use it for local variable.
I may be wrong, but it was my impression that a stack is simply a LIFO
data structure. It doesn't have to have any specific hardware support.
On stackless architectures, a LIFO may have to be simulated by the C
implementation, for auto objects.

It makes life easier. Simply one HW (may/maynot be memroy mapped)
stack pointer is required to refer it across all functions. (when you
are using single stack implementation)

Yes. It curious why so many students of C are bursting to know where C
objects are stored. I would've thought that an assembly language or
machine architecture course would be the proper place to recieve such
information.

I think, There is misnomer in C. C storage classes. I don't understand
why "storage" word is required when it just defines the life of
variable.

-Nishu
 
F

Flash Gordon

Keith Thompson wrote, On 08/02/07 05:49:
Nishu said:
Yes, It is common. Systems can either have Top-down or bottom-up
approach for this kind of implementation. Top down approach is
preferred implementation for stack.
[...]

There is no reason (as far as standard C is concerned) to prefer a
top-down stack over a bottom-up stack. (There may be CPU-specific
reasons.)

On some processors I have used there was no HW reason to prefer one
direction over the other. There was no specific reason in terms of HW
for which of the 7 general purpose address registers you used either.
 
C

Chris Dollin

Nishu said:
I don't see any other alternatives rather than register/stack
allocation for local variables. I would be happy to know alternative
implementations for it.

You could put them in whatever region of store was used for mallocated
memory.
 
D

David Thompson

I'm not so sure it would be that perverse. OS/360 <snip>
Now, when I was using this, C didn't exist. Other languages like
PL/1 and Pascal did. Pascal has a more complex setup than C (the
equivalent of an "auto" variable in an outer function can be referred
to in an inner function, even in the presence of recursion). There's
no reason C couldn't use this technique.
PL/I also had a68-style nesting with downward closure, and was much
more popular on S/360+. FORTRAN did not, nor did COBOL of the day,
although since '85 it does, although I'm not sure it has recursion.
Fortran since '90 has (only) one nesting level, and recursion.

<snip much good>

- formerly david.thompson1 || achar(64) || worldnet.att.net
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top