Tutorial 5

tut5.zip



Quick pointer review

The swap function - ex0_swap.c   Text

Multi-dimensional arrays

Up to this point, we've seen arrays that are one-dimensional. Here are a few examples:


  float temperature[8];   /* How big is this array (bytes), on your machine? */

  int primes[] = { 1 , 2, 3, 5, 7, 11, 13, 17, -1};

  struct employee * employee_list[4096]; /* array of pointers-to-structures */

  char message[] = "Hello CSPP51081\n";

  /* Declaration of main() function: argv is an array of pointers */
  int main(int argc, char * argv[]);

We can also declare multidimensional arrays, that is, arrays with more than one subscript:


  int grades[3][10];  

  char tic_tac_toe[3][3];

  float temp[][6] = { {0,20,40,60,80,100}, {32,68,122,158,194,212} };

Exercise 1: ex1_arr.c   Text

When arrays are used as function arguments, they are passed by reference, and not by value. (This is also true for one-dimensional arrays.)

In C, arrays are stored in row-major order. (In a 2-D matrix, the row is represented by the first index, and the "column" by the second index.) This means that, in memory, grades[0][5] is adjacent to grades[0][6] but not grades[1][5]

Exercise 2: ex2_arr.c   Text

Dynamic Memory Allocatoin

Up to this point, we have been using static memory allocation when we declare variables. We will now look at dynamic memory allocation, where a block of memory is allocated dynamically, ie, at run-time.

Why would we need dynamic memory allocatoin

When we declare an array or structure statically, we need to know the size of that object. For example, this code does not properly declare an array:

  int size;
  printf("How many intergers will you enter?");
  scanf("%d",&size);
  int my_arr[size];

Dynamic memory allocation gives us a work around -- rather than declare a local array, we can declare a pointer, and use malloc to allocate memory dynamically.

We also may use dynamic memory allocation when we want to return a block of memory from a function.
What is the error is this function?

  char * create_string( int i)
  {
    char * str = "This is your new string!\n";
    return str;
  }

Using malloc to allocate memory

We use the library function malloc to allocate a block of memory from the heap:

void * malloc(size_t size);

The argument size indicates the number fo bytes to be allocated. We can use the sizeof operator when we are allocating memory for arrays and structures.

int * pi = (int *) malloc(100 * sizeof(int)); /* Array of 100 integers */

Example 3: ex3_malloc.c   Text

In Example 3, we have a variable, name_arr which is an array of strings, ie, an array of char *.

Now, lets correct our first example from above. Complete Exercise 4:
ex4_malloc.c   Text

Checking the return type of malloc

For simplicity I've left this step from the above examples. However, you will want to remember to check the return type of malloc.

  int * my_arr = (int * )malloc(count * sizeof(int));
  if ( my_arr == NULL)
    exit(1);

What does NULL indicate?

What are the stack and the heap?

When local variables and function arguments are stored on the stack. Dynamically allocated memory, however, is assigned from the heap.

Using free to free memory

The library function free frees a block of memory to the operationg system, so that it is available to be allocated again:

void free(void *ptr);

The argument to free should be a pointer returned by malloc or annother memory allocation function (calloc,realloc).

int main () {
  int * my_arr = (int * )malloc(count * sizeof(int));
  if ( my_arr == NULL) exit(1);

    ...

  free(my_arr);
  return 0;
}

Debugging a running process, using attach

We can use the attach command with gdb to debug a process that is already in execution:

(gdb) attach 25958
Attaching to process 25958
Reading symbols from /home/wax/html/cspp51081/tut5/ex5...done.

...

0xb7f1203b in nanosleep () from /lib/tls/libc.so.6
(gdb) b main
Breakpoint 1 at 0x8048405: file ex5_gdb.c, line 10.
(gdb) where
#0 0xb7f1203b in nanosleep () from /lib/tls/libc.so.6
#1 0xb7f11e8e in sleep () from /lib/tls/libc.so.6
#2 0x08048480 in main () at ex5_gdb.c:20
(gdb) frame 2
#2 0x08048480 in main () at ex5_gdb.c:20
20 sleep(SLEEP);
(gdb) print counter
$1 = 5
Detaching from program: /home/wax/html/cspp51081/tut5/ex5, process 25958
(gdb)

We can also attach the debubber from the command line:

$ gdb ex5 26070

Here, ex5 is the name of the executable, and 26070 is the process ID.

Exercise 5 is a program that forks a child process. Following the above example, set watchpoint on the counter variable in the child process:

Exercise 5:   ex5_gdb.c   Text