Monday, February 27, 2012

Coding lessons: Memory allocation in C

How and where you store things is pretty important, C will take care or a lot for you, it's a pretty high level language, but it does give you pretty enormous power too, direct access to memory is just one of those powers.

In the last coding lesson (some time ago now) I covered pointers and how not only could we give variables names and use the name to access those variables but we could also use a pointer to read the variable from the memory location for the address of where the variable is stored.

In this lesson I'm going to cover a bit more about memory usage.

Allocating memory
To allocate memory we use the memory allocate function called malloc

Malloc will allocate a certain amount of memory during the execution of a program, the function requests memory from the memory heap (not the stack), when the request is granted that memory is reserved for the program.

    #include<stdio.h>
    #include<string.h">
    int main()
    {
    char words[]={"My Malloc String\n"};
    char *p;
    p = (char *)malloc(sizeof(words));
    strcpy(p,words);
    printf("p = %s\n",p);
    printf("words = %s\n",words);
    return(0);
    }


I have introduced a ew function (sizeof())
the sizeof function returns an integer that is the size of the argument givern to is

so
char x[] = "hello";
int length = sizeof(x);


length = 6, five letters and the null terminator.

Anyway, the code, first we've created a string, -which we covered in earlier lessons.
then we declared a pointer.
then used malloc to reserve a space of memory that was the same size as the string, we then copied that string data into the memory that we'd reserved, (that pointer p pointed to).

(there is a bit missing from this program, so scroll to the bottom before you go crazy trying to figure out why your adapted code sample is doing funny things once you've run it loads of times.)

The next function that I'll look at is calloc,
Calloc is slightly different to malloc in that two arguments are needed.
with malloc you can reserve say 50 bytes by writing
pointer = malloc(50);

With calloc you reserve an array of memory, say for storing a list of numbers,
therefore you must give two dimensions (as you;re asking for a 2 dimensional array of space.
that's the amount of rows you plan to save, and the amount of bytes required in those rows.

#include<stdio.h">
#include<stdlib.h">
int main ()
{
int row,n;
int * ptr_data;
printf ("Enter amount: ");
scanf ("%d",&row);
ptr_data = (int*) calloc ( row,sizeof(int) );
for ( n=0; n{
printf ("Enter number #%d: ",n);
scanf ("%d",&ptr_data[n]);
}
printf ("Output: ");
for ( n=0; nprintf ("%d ",ptr_data[n]);
free (ptr_data);
return 0;
}

You see this program, we see that we're going to enter a list of variables, but the programmer does not necessarily know how many items are in the list, so the user is asked first.
this program takes integers,


D:\coding\lesson15>source.exe
Enter amount: 4
Enter number #0: 1
Enter number #1: 2
Enter number #2: 3
Enter number #3: 4
Output: 1 2 3 4


With this sample run we can see that we have a memory allocation of 4 rows, and each row has 4 bytes. (because they are 32 bit numbers)
hence this list was stored in 128bytes of memory.


The other difference between malloc and calloc is that calloc initializes the memory, (writes zeros to all locations) malloc does not.
This means that with malloc you could feasibly read random old data from the memory heap.

The above example miss two very important things.
the first is error checking.
Neither malloc nor calloc guarantee that the memory will be allocated, if the system is out of memory then the system is out of memory and cannot allocate memory, in this case a NULL pointer is returned.
when using the function you should check for a null being returned, because things will not work as expected if you don't get the memory that you asked for!

if (ptr_data==NULL)
{
printf ("Error allocating requested memory");
exit (1);
}


The other thing that you should do, (and if you're using a loop with memory allocation functions) is free the memory that you have reserved, because if you don't you will run out of memory.

in computer terms a program that requests memory from the heap, then never returns it, only ever requesting more is usually thought to have a memory leak. eventually the program will consume all the available resource.

to return memory to the heap once we're finished with it we use the free function.

When we're finished with the memory that our pointer is looking at we just write

free(pointer);

and that un-reserves and returns the memory ready to be used by other programs.

No comments: