Global Variables : Where are they stored ?

M

Mark McIntyre

Kislay said:
What I really wanted to know was where it is stored .

We understand that. The answer has been given!
But you guys tell me that it is implementation specific .

Correct. That /is/ the answer. Obviously you were expecting to be told
the actual place - but consider how many children ask each year where
Santa Claus lives. The answer to that is broadly similar.

Actually this was asked in a job interview .

Thats fine - the correct answer is still "its implementation specific".....
 
M

Mark McIntyre

Podi said:
No offense, but you will not likely to pass our interview :)

No offense in return, but I'd probably turn down the job anyway.
Interviewers who ask daft or unanswerable questions don't do their
company any favours, unless they show a good understanding of why they
asked the question. In which case we'd probably both have a pretty fun
interview discussing the merits of various arcana.
Not in my group. Most of the people here have 10+ years on systems SW.

Well, you and Flash can play "mine is bigger than yours" but I'm voting
with Flash for now... :)
a is not at file scope.

As written by yourself, it was at file scope.
Trivial, same memory area as a. The importance is file scope.

Huh? a and c both have file scope. However c has internal linkage, thats
the difference. Note that scope and linkage are not the same. See 6.2.1
and 6.2.2 of the Standard.

Agree. However, a CPU only has a limited number of registers. It will
most likely be on a stack after some level of function calls.

On modern nonembedded processors, this is AFAIK pretty unlikely in fact.
 
B

Barry Schwarz

Whats all this "file scope" you are bringing into it?

It is the correct terminology for what is called a global variable in
the vernacular.


Remove del for email
 
P

Philip Potter

Podi said:
No offense, but you will not likely to pass our interview :)

The feeling's mutual :)
Agree. However, a CPU only has a limited number of registers. It will
most likely be on a stack after some level of function calls.

Where did you get this idea? Functions "deeper" on the stack will have
saved their registers to their stack frame to make the registers
available to the function currently executing. It doesn't make sense to
use registers for long-term storage of data concerning functions which
aren't currently executing.

On the ARM (which is the processor I'm most familiar with), the usual
calling convention is that the first four arguments are passed in
registers r0-r3, and any function (even with less than four parameters)
can clobber these registers for its own purpose. The return value is
placed in register r0, and the return address in r14. Any function which
calls another function must save any values in these registers which it
would like to keep.

This doesn't apply when you have arguments or return values which are
bigger than the size of a register. I'm not sure what happens then.

Phil
 
F

Flash Gordon

Mark McIntyre wrote, On 29/11/07 00:33:
No offense in return, but I'd probably turn down the job anyway.

Currently I would as well.
Interviewers who ask daft or unanswerable questions don't do their
company any favours, unless they show a good understanding of why they
asked the question. In which case we'd probably both have a pretty fun
interview discussing the merits of various arcana.

An interview with one of the respected CLC regulars (interviewing or
being interviewed by) would be interesting.
Well, you and Flash can play "mine is bigger than yours" but I'm voting
with Flash for now... :)

:-D

Well, it's a bigger grin anyway.
As written by yourself, it was at file scope.

Indeed. If it was not at file scope and I was asked where it was
normally stored (as opposed to the requirements of the C standard) I
would suggest a register or the stack depending on register usage and
the details of the processor. On several implementations I've worked
with it is up to the developer to specify what section the stack is in,
so it could be in a section called "fred" for all the difference it makes.
Huh? a and c both have file scope. However c has internal linkage, thats
the difference. Note that scope and linkage are not the same. See 6.2.1
and 6.2.2 of the Standard.

Of course, if a is not at file scope (as now specified) they will be in
conceptually different areas.
On modern nonembedded processors, this is AFAIK pretty unlikely in fact.

In any case, just stating "on the stack" is incorrect because on a small
leaf function it is very likely to be wrong.

In my embedded days we had to estimate ROM and RAM usage, so that was
two types of memory to deal with. Of course, for RAM usage you had to
look at static storage duration and stack size (I never used a processor
where the implementation did not document a stack for auto variables),
so worst case we were concerned with three "sections". I have not
forgotten dynamic memory allocation, the rules explicitly disallowed
using it. Any further breakdown was an implementation detail you dealt
with when setting up the build environment, and I always set it up so as
to make life easy.

Oh, and I always ensured that *all* RAM was initialised as part of the
power-up RAM test, so there was in a real practical sense never an
"uninitialised section".

It was generally me that was responsible for the startup code and linker
scripts on any project I was on, so I always knew exactly where
everything was and how static variables were initialised.
 
P

Podi

Mark McIntyre wrote, On 29/11/07 00:33:



Indeed. If it was not at file scope and I was asked where it was
normally stored (as opposed to the requirements of the C standard) I
would suggest a register or the stack depending on register usage and
the details of the processor. On several implementations I've worked
with it is up to the developer to specify what section the stack is in,
so it could be in a section called "fred" for all the difference it makes.



Of course, if a is not at file scope (as now specified) they will be in
conceptually different areas.

Yes, linkage is right term. I was trying to say that one can access
a's memory from other files by "extern char a;" but not the case for
"c".
In any case, just stating "on the stack" is incorrect because on a small
leaf function it is very likely to be wrong.

The point I am stressing is that we prefer people who know about the
memory locations for our sw, which runs on Windows (desktop and CE),
Linux (desktop and embedded), other OSes such as cell phones,
handhelds, etc.

We have many large data structures that are like.

typedef struct
{
double a;
long b;
long long c;
short d;
short e;
double f;
// ...
double z;

} Data;

// developers who "does not care" about process memory image are
likely to write functions like
void A(Data d)
{
// do something with d
}

void B(Data d)
{
A(d);
}

// Continues with functions C, D, ..., X, Y, Z
void Y(Data d)
{
X(d);
}

// After many levels, would d still be in registers in function A?
// Even so, there would be lots of memory got pushed to the stack
along the way.
void Z(Data d)
{
Y(d);
}

// developers who "does care" about process memory image will most
likely write functions like
void A(const Data* d)
{
// do something with d->whatever
}

void B(const Data* d)
{
A(d);
}

// ...
void Z(const Data* d)
{
Y(d);
}

Sure, one can write correct C programs without ever knowing this
"general concept" (stack, heap, data segment, etc.), but it is
important when the SW runs on systems with limited resources.

So this is the answer to why we ask this question in our interviews.
 
F

Flash Gordon

Podi wrote, On 29/11/07 22:03:
Yes, linkage is right term. I was trying to say that one can access
a's memory from other files by "extern char a;" but not the case for
"c".

Static or not only affects whether the name is visible and on many
systems will not affect where it is stored. A pointer can easily be
generated allowing code in another translation unit to access it.
The point I am stressing is that we prefer people who know about the
memory locations for our sw, which runs on Windows (desktop and CE),
Linux (desktop and embedded), other OSes such as cell phones,
handhelds, etc.

Ah, you mean systems with lots (more than 8K) or RAM!
We have many large data structures that are like.

typedef struct
{
double a;

// developers who "does not care" about process memory image are
likely to write functions like
void A(Data d)
{
// do something with d
}

// After many levels, would d still be in registers in function A?
// Even so, there would be lots of memory got pushed to the stack
along the way.
void Z(Data d)
{
Y(d);
}

// developers who "does care" about process memory image will most
likely write functions like
void A(const Data* d)
{
// do something with d->whatever
}

<snip>

If that is your concern then ask a more directly related question, such
as "how would you ass a large structure to a function?" With a
supplementary question of "now discuss what size you would switch from
one method of passing to another?" Or you could show some problem code
and ask what the problems are with it.
Sure, one can write correct C programs without ever knowing this
"general concept" (stack, heap, data segment, etc.), but it is
important when the SW runs on systems with limited resources.

So this is the answer to why we ask this question in our interviews.

The problem with passing large structs can be understood perfectly well
in terms of the C model of static, automatic and allocated duration
together with knowing that C uses pass-by-value. It does not require any
knowledge of stacks, heaps. data segments etc.
 
J

jameskuyper

Podi wrote:
....
The point I am stressing is that we prefer people who know about the
memory locations for our sw, which runs on Windows (desktop and CE),
Linux (desktop and embedded), other OSes such as cell phones,
handhelds, etc.

We have many large data structures that are like.

typedef struct
{
double a;
long b;
long long c;
short d;
short e;
double f;
// ...
double z;

} Data;

// developers who "does not care" about process memory image are
likely to write functions like
void A(Data d)
{
// do something with d
}

void B(Data d)
{
A(d);
}

// Continues with functions C, D, ..., X, Y, Z
void Y(Data d)
{
X(d);
}

// After many levels, would d still be in registers in function A?
// Even so, there would be lots of memory got pushed to the stack
along the way.
void Z(Data d)
{
Y(d);
}

// developers who "does care" about process memory image will most
likely write functions like
void A(const Data* d)
{
// do something with d->whatever
}

void B(const Data* d)
{
A(d);
}

// ...
void Z(const Data* d)
{
Y(d);
}

You don't have to know where the data is stored to prefer the second
implementation over the first one. It's sufficient to know that a
separate copy of the entire structure is created by each function call
in the first implementation, while the second one only creates enough
extra room to store a copy of the pointer.

If you are using an implementation with only a limited amount of
memory, you are justifiably more paranoid about about the amount of
memory used, but paying attention to the precise details of the
location of the memory is appropriate only for code that is so
implementation-specific that it will never be used anywhere where such
details might be different.

That doesn't describe any program I'm currently responsible for,
though I'm sure it's true for many other programs.
 
K

Keith Thompson

Podi said:
The point I am stressing is that we prefer people who know about the
memory locations for our sw, which runs on Windows (desktop and CE),
Linux (desktop and embedded), other OSes such as cell phones,
handhelds, etc.

We have many large data structures that are like.

typedef struct
{ [lots of members]
} Data;

// developers who "does not care" about process memory image are
likely to write functions like
void A(Data d)
{
// do something with d
}

void B(Data d)
{
A(d);
}

// Continues with functions C, D, ..., X, Y, Z
void Y(Data d)
{
X(d);
}

// After many levels, would d still be in registers in function A?
// Even so, there would be lots of memory got pushed to the stack
along the way.
void Z(Data d)
{
Y(d);
}

// developers who "does care" about process memory image will most
likely write functions like
void A(const Data* d)
{
// do something with d->whatever
}

void B(const Data* d)
{
A(d);
}

// ...
void Z(const Data* d)
{
Y(d);
}

Sure, one can write correct C programs without ever knowing this
"general concept" (stack, heap, data segment, etc.), but it is
important when the SW runs on systems with limited resources.

So this is the answer to why we ask this question in our interviews.

In the code you posted, passing large Data object by value will cause
a new copy of the same object to be created on each call. Passing
pointers to the Data objects gets rid of this overhead. This is true
based just on the semantics defined by standard C; knowing that the
pointer approach reduces memory usage doesn't require knowing *where*
the memory is going to be allocated. If parameters were all allocated
on the heap rather than on the stack (as they actually are in some
systems), or even scribbled in leather bound books, the issue would be
pretty much the same.

Sure, there are contexts where you care about where the memory is
allocated rather than just how much. For example, "heap" memory might
happen to be more plentiful than "stack" memory in a given
implementation, or ROM might cheaper than ROM. But those aren't
really C questions; they're questions about a particular environment,
and are likely to apply to programs written in any language for that
environment.

I don't suggest that questions about memory segments aren't important,
or that you shouldn't be asking about them in interviews, just that
such questions aren't really about C.
 
P

Podi

You don't have to know where the data is stored to prefer the second
implementation over the first one. It's sufficient to know that a
separate copy of the entire structure is created by each function call
in the first implementation, while the second one only creates enough
extra room to store a copy of the pointer.

Maybe you and Flash are right, the exact memory location is
implementation-specific. However, from my interview experience, if I
described the "general" process memory image when I was asked, I'd
pass this particular question. As a matter of fact, I was asked the
exact question when I interviewed for my current position. My believe
is that, asking it in such a subtle manner is sort of on purpose.

Essentially, we are looking for systems SW developers who know a bit
more on the system level, than just on the language level. This
question is just one way to make an assessment.
 
B

Barry Schwarz

Ah, I usually ask this question in job interviews. I have also been
asked many times in when I was looking for a job.

In my opinion, it is important for a systems software engineer (who
works on embedded or device driver software) to know the "general"
memory structure of a process image.

In general, it is safe to say the following since it is similar on
Unix, Linux, Windows, ...

Do you mean that this depends only on the operating system and not on
the compiler? That every compiler for linux does it the same way?
char *a; // uninitialized data segment

Unfortunately my system doesn't have a data segment.
char *b = "hello"; // b is in uninitialized data segment, b's value
"hello" is in constant data segment

So you claim there are at least three data segments (uninitialized,
constant, and initialized).
static char c; // file scope, not visible from other files
char d[8] = "world"; // initialized data segment, array of 8 bytes,
initialized first 6

All eight characters of the array are initialized.
// char d[800]; will cause file size of executable to be increased

You are assuming that the initialized array is stored as such in the
executable. It is quite possible that the array will be created just
like e below but the startup code that runs before main will
initialize it.
char e[8]; // uninitialized data segment
// char e[800]; will cause process to require more memory, but same
executable file size

// foo is in the code segment

My system doesn't have a code segment either.
void foo(char f) // f is copied onto stack

My system doesn't have a stack either. If it did, f would not be
copied onto it. f is the formal parameter of the function. What is
copied onto the stack (in those systems where it is relevant) is the
value of the actual argument.
{
char g; // allocated from stack
static char h; // data segment, not on stack so the value is
"static"
char *i = malloc(8); // heap, potential memory leak

No heap either.
// It is also important to know the difference of b and d
d[0] = 'h'; // OK
b[0] = 'y'; // likely to get a segmentation fault

My system doesn't have segmentation faults either. (In this case, I
would get a protection exception.) The only thing you can say for
sure is that the statement invokes undefined behavior.

If you want to give system specific advise, you would be better off in
a system specific newsgroup.


Remove del for email
 
P

Podi

I don't suggest that questions about memory segments aren't important,
or that you shouldn't be asking about them in interviews, just that
such questions aren't really about C.

I agree, and thanks for all the corrections on my posts with my
limited knowledge on the C standard.

Since we deal with mostly Windows (desktop + many variants of CE) and
Linux (many variants of desktop + many variants of embedded Linux),
and our code happens to be in C and C++, we are looking for people who
are at least familiar with the concept of memory layout as described
in the following.

http://dirac.org/linux/gdb/02a-Memory_Layout_And_The_Stack.php
http://blogs.msdn.com/sloh/archive/2005/02/25/380475.aspx


Since we also deal with many compilers, some of which do not comply
with "the standard", we are (at least I am) slacking quite a bit on
the correct definition of C :)

At the end of the day, the answer "implementation-specific" to OP is
wise and correct, but it will unlikely satisfy the interviewer. The
expected answer is to describe the "general" memory layout of a
process, given the simple, yet subtle question asked in C. And never
heard of "stack/heap" is sort of a no-no :)

Cheers!
 
R

Richard Harter

I don't suggest that questions about memory segments aren't important,
or that you shouldn't be asking about them in interviews, just that
such questions aren't really about C.

Not, perhaps, in comp.lang.c. However they are on point if one
is talking about using C in the "real world".



Richard Harter, (e-mail address removed)
http://home.tiac.net/~cri, http://www.varinoma.com
In the fields of Hell where the grass grows high
Are the graves of dreams allowed to die
 
W

Walter Roberson

On Thu, 29 Nov 2007 16:13:59 -0800, Keith Thompson
Not, perhaps, in comp.lang.c. However they are on point if one
is talking about using C in the "real world".

Only if in the "real world" the memory arrangement is unique to C
on that particular system. If all executables for that particular
system use the same memory arrangement, then the question is not
one about using *C* "in the real world", it is one about the system
architecture independant of C.
 
S

santosh

Walter said:
Only if in the "real world" the memory arrangement is unique to C
on that particular system. If all executables for that particular
system use the same memory arrangement, then the question is not
one about using *C* "in the real world", it is one about the system
architecture independant of C.

I would expect system level C code like operating system kernels,
compilers, debuggers, linkers etc., to need to know about the memory
layout of their targets, but certainly plain, application programs
shouldn't need this low level knowledge. Part of the reason for using a
high level language like C in the first place is to turn over the
management of such details to the machine.
 
K

Keith Thompson

Podi said:
I agree, and thanks for all the corrections on my posts with my
limited knowledge on the C standard.

Since we deal with mostly Windows (desktop + many variants of CE) and
Linux (many variants of desktop + many variants of embedded Linux),
and our code happens to be in C and C++, we are looking for people who
are at least familiar with the concept of memory layout as described
in the following.

http://dirac.org/linux/gdb/02a-Memory_Layout_And_The_Stack.php
http://blogs.msdn.com/sloh/archive/2005/02/25/380475.aspx

In other words, you're looking for knowledge of memory layout on
Windows and Linux systems. In the scope of systems that have, or can
have, C implementations, Windows and Linux are actually quite similar
to each other.
Since we also deal with many compilers, some of which do not comply
with "the standard", we are (at least I am) slacking quite a bit on
the correct definition of C :)

Really? Very few compilers (yet) fully implement the C99 standard,
but I thought that almost all current C compilers conform reasonably
well to C90, at least in some (possibly non-default) mode. Unless
you're using some very old systems, I'm surprised that you'd be using
non-conforming compilers.
At the end of the day, the answer "implementation-specific" to OP is
wise and correct, but it will unlikely satisfy the interviewer. The
expected answer is to describe the "general" memory layout of a
process, given the simple, yet subtle question asked in C. And never
heard of "stack/heap" is sort of a no-no :)

Sure, nothing wrong with that in the context you're concerned with.

But you might be surprised at how much useful work you can get done
without going beyond what's guaranteed by the C standard.
 
S

santosh

Keith said:
Really? Very few compilers (yet) fully implement the C99 standard,
but I thought that almost all current C compilers conform reasonably
well to C90, at least in some (possibly non-default) mode. Unless
you're using some very old systems, I'm surprised that you'd be using
non-conforming compilers.

Some posters have mentioned that some embedded systems have only
non-conforming compilers, even for C90, since the peculiar nature of
such systems mean that a compiler with "special extensions" is more
useful than one completely conforming to standard C.

<snip>
 
R

Richard Harter

On Fri, 30 Nov 2007 17:40:52 +0000 (UTC),
Only if in the "real world" the memory arrangement is unique to C
on that particular system. If all executables for that particular
system use the same memory arrangement, then the question is not
one about using *C* "in the real world", it is one about the system
architecture independant of C.

I opine you're missing the point. If one is going to program
effectively, one should have a general understanding of how
computers work, how operating systems typically work, and the
various ways resources are allocated and managed. Without that
knowledge it is all too easy (particularly in C) to write code
that is horribly inefficient or even just plain doesn't work.


Richard Harter, (e-mail address removed)
http://home.tiac.net/~cri, http://www.varinoma.com
In the fields of Hell where the grass grows high
Are the graves of dreams allowed to die
 
K

Keith Thompson

santosh said:
Some posters have mentioned that some embedded systems have only
non-conforming compilers, even for C90, since the peculiar nature of
such systems mean that a compiler with "special extensions" is more
useful than one completely conforming to standard C.

Sure, but the previous poster was talking about Linux and Windows
systems.
 
S

santosh

Keith said:
Sure, but the previous poster was talking about Linux and Windows
systems.

He also mentioned Windows CE and various versions of embedded Linux.
However these particular embedded targets should have fully C90
conformant compilers. Perhaps his firm also develops for more exotic
chips like DSPs and so on.
 

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,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top