Main

Lab 4

In this lab we will practice using the debugger, allocating and deallocate memory in C++.

Some introductory materials on debuggin are available at the Resources page. Note: Unless you install GNU compilers on OSX, the compiler you get from XCode is not really gcc (even though there is an alias allowing you to call it gcc). The LLVM-based compilers on Macs work with the LLVM debugger, lldb, which has a different interface from gdb but you can do everything there that you can with gdb.

Debugging

Consider the following program that allocates and uses a 2-D int array in C.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
	int **num;
	int size = 5, i, j;

	// Allocate memory for 2-D int array
	num = (int **) malloc (size * sizeof(int *));
	for (i = 0; i < size; i++)
		num[i] = (int *) malloc (size * sizeof(int *));

        // Set values
	for (j = 0; j < size; j++)
		num[i][j] = i * size + j;

	// Print values
	for (i = 0; i < size; i++) {
		for (j = 0; j < size; j++) {
			printf("%d ", num[i][j]);
		}
		printf("\n");
	}

	// Deallocate memory
	for (i = 0; i <= size; i++)
		free(num[i]);
	free(num);
}

Compile this program (notice the -g flag, which we use when we plan to debug the code -- it tells the compiler to preserve symbol information for all local symbols, as well as source code details).

gcc -g -std=c11 -o num num.c 

When you run this example with ./num you will get an error "Segmentation Fault".

Use the debugger to identify the line where the program crashes. In some cases, the error is somewhere else, and we will talk about strategies for locating the origin of the problem.

After creating a version of this code that does not seg. fault, introduce an infinite loop, and use the debugger to locate the problem and fix it.

C++ dynamic memory allocation

In this task, implement the same functionality as the code above in C++. Compile with g++ -g -std=c++14. If you encounter memory problems, use the debugger. Check for memory leaks with valgrind.

Some useful examples are given below. In C++, we allocate dynamic memory with the new operator and free it with delete. The process is otherwise the same as for C. For more details, refer to the TICPP book and/or this page.

For example, this C code allocates a 4 by 2 array of floats:

 
float **arr = NULL;
arr = (float **) malloc(4 * sizeof(float *)); // row pointers
for (int i = 0; i < 2; i++) 
    arr[i] = (float *) malloc (2 * sizeof(float)); // columns

In C++, the equivalent code is:

float **arr = nullptr; // nullptr is the C++ equivalent of NULL
arr = new float * [4]; // row pointers
for (int i = 0; i < 2; i++) 
    arr[i] = new float[2]; // columns

To free memory, in C you could do the following:

 
for (int i = 0; i < 2; i++) 
    free(arr[i]); // columns
free(arr); // row pointers

The equivalent code freeing memory in C++ is:

 
for (int i = 0; i < 2; i++) 
    delete [] arr[i]; // columns
delete [] arr; // row pointers

Note that we have to use delete [] to free arrays of pointers. If you are freeing a single pointer, then you simply use delete, e.g.,

float *ptr = new float;
*ptr = 3.14;
delete ptr;

Green Marinee theme adapted by David Gilbert, powered by PmWiki