PC based compiler/linkers often build memory images of programs which
are segmented in
a manner similar to that shown above. The program's machine code
goes in its own segment(s)
of memoery, global data and static
data go in a separate data segment. The stack segment is
used for storage of return addresses during calls to functions as well
as local (temporary) variables.
Finally the heap (often the remainder of memory in the PC) is available
for use by dynamically
created variables.
int i; /* i is a global variable */
int main() {
.
.
i = 20;
.
}
void SomeFunction() {
i = 21; /* global variables are visible to all
functions */
}
void SomeFunction() {
static int i;
.
.
.
}
void SomeFunction() {
int i;
.
.
.
}
Local variables are declared within a function and are not visible
to other functions.
Local variables are assigned memory space when the function is called.
This space
is freed-up when the function terminates. This is in contrast
to the behavior of global
and static variables. As a consequence of this, you can not use
local variables to
store information which may be needed the next time the function is
executed. There
are other consequences also. Suppose you have a function such
as the following:
char *MakeHello() {
char HelloString[6];
strcpy(HelloString,"Hello");
return(HelloString);
}
This function simply creates a string which contains the word "Hello"
and returns its
address. The address returned points to a variable which is stored
on the program stack.
The problem with this is that when the function returns, the area occupied
by the string
is freed-up and so may be used for storage of return addresses or other
local data. You
can not therefore guarantee that the memory pointed to by the returned
address will continue
to contain the characters which make up "Hello". One way to ensure
correct behaviour is
to declare "HelloString" as a static (or even global) variable.
This will ensure that the space
alotted to the string is used by the string and nothing else.
The downside of this? Global
and static data make poor use of memory. You might declare a
large number of variable
as global which are only used by the program during its initialisation.
These variables, though
unused for the remainder of the program's operation will continue to
occupy memory space.
Global variable present a special difficulty in that they become a
management headache for the
programmer. Suppose you create a global variable called i which
is used throughout the program
in various loops or other purposes. How can you be sure of the
meaning of the data in this
variable at any one time? Word of advice: Create global variables
sparingly.
There are various dynamic memory management functions available to the
C-programmer. Microsoft
prototypes these functions in the file "malloc.h". We will only
deal with two of them here: malloc and
free.
malloc is used as follows:
address of allocated data = malloc(size of data block required expressed in bytes);
Its purpose is to ask the operating system to set aside a block of memory
of a particular size. If the
memory is allocated successfully, the function returns the address
of the data block, otherwise it returns
null (or zero).
free operates as follows:
free(address of block of data
which was returned by a previous call to malloc);
Free tells the operating system that the program is finished with the
block of memory and that it is ok to release
it for use by other programs. It is important that your program
frees-up all blocks of memory which it
has allocated for itself when it is finished. Otherwise, you
run the risk of using up all of the memory withiin
your computer necessitating a reboot.
Example:
void SomeFunction(void)
{
int *MyDynamicArray;
.
.
.
/* create an array of 2000 integers by requesting
a block of data
which is 2000 * the
number of bytes in an integer long */
MyDynamicArray = (int *)malloc(2000*sizeof(int));
if (MyDynamicArray != NULL) /* if allocation
was successful */
{
/* do something with
the array of integers */
.
.
.
/* and don't forget
to release the memory when done */
free(MyDynamicArray);
}
}