290 likes | 485 Views
Winter 2009 Tutorial #6 Arrays Part 2, Structures, Debugger. COMP 1402. Overview of Tutorial #6. Arrays revisited, array indexing Memory allocation Freeing memory Basic Data structures Debugger revisited Exercises. Arrays Revisited. We’ve seen arrays in tutorial #5: Declaration:
E N D
Winter 2009 Tutorial #6 Arrays Part 2, Structures, Debugger COMP 1402
Overview of Tutorial #6 • Arrays revisited, array indexing • Memory allocation • Freeing memory • Basic Data structures • Debugger revisited • Exercises
Arrays Revisited • We’ve seen arrays in tutorial #5: • Declaration: int array[10]; //define an array of 10 ints • Storing values: array[5] = 4; • Accessing elements: if(array[5]>=3)… • Looping through 1d, 2d and 3d arrays • for loops, while loops.
Arrays are Pointers • When we declare an array “a” of n ints in C, a consecutive block of n ints is reserved in memory. • The first address of that memory block is stored in a (address of a[0]). int a[5]; a a[0] a[1] a[2] a[3] a[4]
Arrays are Pointers (2) • We’ve seen pointers briefly when we talked about passing parameters by reference: int *ptr;ptr is a pointer, it will contain an address of an int in memory. int array[10]; here array is also a pointer, it points to the first address in the block of 10 ints that has been reserved or allocated in memory. This is why we can pass an array as parameter to a function and change the contents of the array inside that function (since we always pass the array by reference).
Arrays are Pointers (3) • Knowing that arrays are pointers, we can access elements in arrays in different ways: temp = array[4]; will store the value of array[4] into temp temp = *(array+4); this will do the same thing • array is pointing at the first int of the array in memory (array[0]), array+4 is the address of the 5th value in the array (array[4]), to get the value we use the dereference operator *. Don’t forget the ( ), *a+4 is not the same!
Arrays are Pointers (4) • If we take our array example again, here are the addresses for the elements of the array. • To get the values we would write: *a, *(a+1)… int a[5]; a *a *(a+1) *(a+2) *(a+3) *(a+4) a+1 a+2 a+3 a+4
Memory Allocation • Up until now, we assume we know the size of the array at compile time. • ex: int a[10]; creates an array of 10 ints • What if we don’t know the size in advance, only at runtime? • We can’t change the size of an array once it has been declared. • What if we want the user to decide the size of an array at runtime? • Now that we know that arrays are pointers, we can declare arrays in a different way…
Memory Allocation (2) • Pointers are used to “point” to a memory address. • We can create an array by creating a pointer that will point to a reserved block of memory. • How do we do this? • In C we have a function called malloc() which will reserve a block of memory of a specified size and return the address of the start of that block (you must add #include <stdlib.h> to your code to be able to use malloc).
Memory Allocation (3) int *array; // our array pointer array = (int *) malloc(10*sizeof(int)); • This instruction will reserve a block of memory of 10 ints. sizeof() will give the size in bytes of a type or structure, in this case an int (4 bytes). • If there was not enough memory to allocate, then array will be NULL (points to nowhere). • Otherwise we can then use array as a regular 1D array. We can access elements like we’ve seen before: array[2]=5; or *(array+2)=5;
Freeing Memory • When we allocate memory with malloc() it remains reserved for the duration of the program. • When the array is no longer needed (at the end of a function or of the main) we should free the memory that was reserved for it. • If we don’t then the program could eat up memory until there is none left (memory leak). ex: if we have a malloc statement inside a for or while loop but no free statement.
Freeing Memory (2) • How do we free the memory? • by using the free() function: int *array; // our array pointer array = (int *) malloc(10*sizeof(int)); //do some operations free(array); // this frees the memory // reserved for “array”
Freeing Memory (3) • free( ) can only be used on memory that was allocated by malloc, calloc, realloc, etc… (we will see those other functions later). • Trying to free memory declared differently won’t work (will crash). Ex: int var[10]; // we declare an array “var” free(var); // this won’t work! Segmentation Fault.
Basic Data Structures • If we need to create objects more complex than one int or an array we can create data structures. • A data structure can be composed of different data types (int, float, strings, arrays, etc…) and they can also include other data structures (nested structures).
Basic Data Structures (3) Basic structure construct: Defining a structure as a type: struct { type1 field1; type2 field2; … } structName; typedef struct { type1 field1; type2 field2; … } typeName;
Basic Data Structures (3) • Let’s start with a simple example. We want to create a data structure that will represent a shipping box. BOX: A shipping box has: • a width (int) • a height (int) • a length (int) • a weight (float) Width Length Height Weight
Creating a Data Structure • To create a structure in C we use the struct instruction. The typedef instruction creates a new type called BOX. typedef struct { int width; // width of the box int height; //height of the box int length; // length of the box float weight; //weight of the box } BOX;
Declaring/Accessing a Data Structure • Since we defined our BOX structure as a new type (with typedef) we can declare an instance of that structure as: BOX myBox; • To access the fields of the structure we use the . operator: myBox.length=5; myBox.weight=2.3;
Array of Structures • We can also define an array of structures: BOX array[5]; // creates an array of // 5 box structures • We can also define an array of structures using malloc( ): BOX *array; array = (BOX *) malloc(10*sizeof(BOX)); array[5].length = 42; // we can access each of // the structures this way
Debugger Revisited (gdb) • We briefly saw the debugger gdb a few weeks ago. • In order to run a program through gdb a parameter needs to be added at compile time: -g (ex: gcc –g –o hello hello.c) • Once the program has been compiled with the -g parameter we can start the program in gdb: gdb hello
gdb - list • Once gdb is started with the program name we can list the code by typing list • If the program is too large to fit all on the screen, it will wait till the user presses the Enter key to continue with the extra lines. • You can list a specific part of code by typing the line number (ex: list 8 will list line 8 and the ones before and after it, if there are any).
gdb - Running • To run your program without stopping you can type the run command at the gdb prompt. This might not be the most helpful way to solve bugs or find problems. • run will execute your program as if it was started from the command line (along with parameters if any). If all goes well the program will end normally. If there are errors gdb should identify the function or the line that caused the error.
gdb - Breakpoints • You can add breakpoints in your code with gdb. When you run the code, it will stop at your designated breakpoints. • breakplace: this will add a breakpoint at a certain place. For example break main will put a breakpoint at the first line of main(). You could also do break 10 which will add a breakpoint to the 10th line of your code (according to the line numbers given by list) • info break: this will list all of your breakpoints. • delete N: will delete the breakpoint number N.
gdb - Continue, Step and Next • After you placed one or more breakpoints, you can run your code. It will stop at the first breakpoint. • continue will continue running the program until the next breakpoint. • step will go through the code line by line after the breakpoint. • nextis similar to step, but if the line of code contains a function call, using next will execute the function call then stop at the next line (step would instead step through every line of the called function).
gdb - Viewing Value of a Variable • There are two basic ways to view the contents of variables in gdb • display name: when the program is running you can set which variables will be printed to the screen at every step or next command. You can add multiple values to be displayed at the same time. • printname: this will directly print the current value of the variable “name” to the screen if it exists. • You can only print or displayvariables that have been declared in the current context/function and only when you are running the code with run (if you try to print a variable before typing run it will say there is no such symbol).
gdb - Example • Suppose we have the following code: Line # hello.c 1 2 3 4 5 6 7 8 9 10 #include <stdio.h> int main() { int a,b; a=10; b=6; a++; b--; a = a-b; }
gdb - Example (2) • We compile and start gdb: gcc –g –o hello hello.c gdb hello (gdb) (gdb) break main Breakpoint 1 at 0x8048365: file hello.c, line 5. (gdb) run Breakpoint 1, main () at hello.c:5 5 a=10; Compile with –g flag Start gdb with program name gdb command prompt Add breakpoint at the start of main gdb adds breakpoint to main (line 5) Start running the program Reaches first breakpoint (stops before executing line 5)
gdb - Example (3) (gdb) display a 1: a = 7528436 (gdb) display b 2: b = 10363856 (gdb) step 6 b=6; 2: b = 10363856 1: a = 10 (gdb) step 7 a++; 2: b = 6 1: a = 10 Add a and b to the list of displayed variables (notice the uninitialized values) Take one step (execute line 5) Next line to be executed Current values of a and b Take one step (execute line 6) And so on until the end…
Tutorial #6 Exercises • Go to the class webpage and do the exercises for Tutorial 6. • Use the Makefile to compile the exercises! • it’s there to save you time • Even if it isn’t specified in the exercise, you can used gdb to help fix your errors (same goes for your assignments).