1 / 42

Compilation / Pointers Debugging 101

Compilation / Pointers Debugging 101. Compilation in C/C++. hello.c. tmpXQ.i (C code). Compiler. Preprocessor. stdio.h. hello.o (object file). Preprocesser. A single-pass program that Include header files Expands macros Control conditional compilation Remove comments.

brit
Download Presentation

Compilation / Pointers Debugging 101

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Compilation / PointersDebugging 101 .

  2. Compilation in C/C++ hello.c tmpXQ.i (C code) Compiler Preprocessor stdio.h hello.o (objectfile)

  3. Preprocesser A single-pass program that • Include header files • Expands macros • Control conditional compilation • Remove comments

  4. #include directive #include ”foo.h” • Include the file “foo.h”, from current directory #include <stdio.h> • Include the file “stdio.h” from the standard library directory (part of compiler installation)

  5. complex.h struct Complex { double _real, _imag; }; Complex addComplex(Complex, Complex); Complex subComplex(Complex, Complex); ... complex.c #include <math.h> #include “complex.h” // implementation Complex addComplex(Complex a, Complex b) { … MyProg.c #include “complex.h” int main() { Complex c; … Modules & Header files Complex.c

  6. Header files Header file contain • Definition of data types • Declarations of functions & constants That are shared by multiple modules. #include directive allows several modules to share the same set of definitions/declarations

  7. #define directive #define FOO 1 … int x = FOO; is equivalent to … int x = 1;

  8. #define with arguments #define square(x) x*x b = square(a); is the same as b = a*a;

  9. #define -- cautions #define square(x) x*x b = square(a+1); c = square(a++); Is it what we intended? b = a+1*a+1; // b = 2*a+1; c = a++*a++; // c = a*a; a+=2;

  10. #define #define directive should be used with caution Alternative to macros: • Constants enum { FOO = 1; }; or const int FOO = 1; • Functions – inline functions (C++, later on)

  11. #if directive • Allows to have conditional compilation #if defined(DEBUG) // compiled only when DEBUG exists printf(“X = %d\n”, X); #endif

  12. #if – header safety Complex.h: struct Complex { … MyStuff.h: #include “Complex.h” Main.c #include “MyStuff.h” #include “Complex.h” Error: Complex.h:1: redefinition of `struct Complex'

  13. #if – header safety Complex.h (revised): #if !defined(COMPLEX_H) #define COMPLEX_H struct Complex { … #endif Main.c: #include “MyStuff.h” #include “Complex.h” // no error this time

  14. Preprocessor We can test what the preprocessor does > gcc –E hello.c will print the C code after running preprocess

  15. assert.h #include <assert.h> // Sqrt(x) - compute square root of x // Assumption: x non-negative double Sqrt(double x ) { assert( x >= 0 ); // aborts if x < 0 … If the program violates the condition, then assertion "x >= 0" failed: file "Sqrt.c", line 7 <exception> • The exception allows to catch the event in the debugger

  16. assert.h Important coding practice • Declare implicit assumptions • Sanity checks in code • Check for violations during debugging/testing Can we avoid overhead in production code?

  17. assert.h #undef assert // procedure that actually prints error message void _assert(char* file, int line, char* test); #ifdef NDEBUG #define assert(e) ((void)0) #else #define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__, #e)) #endif

  18. Compilation • Takes input C-code and produces machine code (object file) • gcc –c Main.c • Main.c  Main.o • The object file does not contain all external references • It leaves names, such as “printf”, “addComplex”, etc. as undefined references

  19. Complex.c Complex.o Main.c Main.o Preprocessor Compiler Linker Linking • Combines several object files into an executable file • No unresolved references Main libc.a

  20. Link errors The following errors appear only at link time • Missing implementation > gcc -o Main Main.p Main.o(.text+0x2c):Main.c: undefined reference to `foo' • Duplicate implementation > gcc -o Main Main.o foo.o foo.o(.text+0x0):foo.c: multiple definition of `foo' Main.o(.text+0x38):Main.c: first defined here

  21. Memory Arrangement • Memory is arrange in a sequence of addressable units (usually bytes) • sizeof( <Type> ) return the number of units it takes to store a type. • sizeof(char) = 1 • sizeof(int) = 4 (on most of our machines)

  22. Memory int main() { char c; int i,j; double x; … c i j x

  23. Arrays Defines a block of consecutive cells int main() { int i; int a[4]; … i a[0] a[1] a[2] a[3]

  24. Arrays • C does not provide any run time checks int a[4]; a[-1] = 0; a[4] = 0; This will compile and run (no errors) …but can lead to unpredictable results. • It is the programmer’s responsibility to check whether the index is out of bounds…

  25. Arrays • C does not provide array operations int a[4]; int b[4]; … a = b; // illegal if( a == b ) // illegal …

  26. Array Initialization int arr[3] = {3, 4, 5}; // Good int arr[] = {3, 4, 5}; // Good - The same int arr[4] = {3, 4, 5}; // Good - The last is 0 int arr[2] = {3, 4, 5}; // Bad int arr[2][3] = {{2,5,7},{4,6,7}}; // Good int arr[2][3] = {2,5,7,4,6,7}; // Good - The same int arr[3][2] = {{2,5,7},{4,6,7}}; // Bad int arr[3]; arr = {2,5,7}; // Bad - array assignment only in initialization

  27. Pointers int main() { int i,j; int *x; // x points to an integer i = 1; x = &i; j = *x; x = &j; (*x) = 3; i j x 1

  28. Pointers int main() { int i,j; int *x; // x points to an integer i = 1; x = &i; j = *x; x = &j; (*x) = 3; i j x 1 0x0100 0x0100

  29. Pointers int main() { int i,j; int *x; // x points to an integer i = 1; x = &i; j = *x; x = &j; (*x) = 3; i j x 1 1 0x0100 0x0100

  30. Pointers int main() { int i,j; int *x; // x points to an integer i = 1; x = &i; j = *x; x = &j; (*x) = 3; i j x 1 1 0x0104 0x0100

  31. Pointers int main() { int i,j; int *x; // x points to an integer i = 1; x = &i; j = *x; x = &j; (*x) = 3; i j x 1 3 0x0104 0x0100

  32. Pointers • Declaration <type> *p; p points to objects of type <type> • Pointer  value *p = x; y = *p; *p refers to the object p points to • value  pointer &x - the pointer to x

  33. Example – the swap function Does nothing Works void swap(int a, int b) { int temp = a; a = b; b = temp; } …. int main() { int x, y; x = 3; y = 7; swap(x, y); // now x==3, y==7 …. void swap(int *pa, int *pb) { int temp = *pa; *pa = *pb; *pb = temp; } …. int main() { int x, y; x = 3; y = 7; swap(&x, &y); // x == 7, y == 3 …

  34. Pointers & Arrays int *p; int a[4]; p = &a[0]; *(p+1) = 1; // assignment to a[1]! p a[0] a[1] a[2] a[3]

  35. Pointers & arrays Arrays are essentially constant pointers int *p; int a[4]; p = a; // same as p = &a[0] p[1] = 102; // same as *(p+1)=102; *(a+1) = 102; // same p++; // p == a+1 == &a[1] a = p; // illegal a++; // illegal

  36. Pointers & Arrays int foo( int *p ); and int foo( int a[] ); Are declaring the same interface • In both cases, a pointer to int is being passed to the function foo

  37. Pointer Arithmetic int a[4]; int *p = a; char *q = (char *)a; // Explicit cast // p and q point to the same location p++; // increment p by 1 int (4 bytes) q++; // increment q by 1 char (1 byte) a[0] a[1] a[2] a[3] p q

  38. Pointer arithmetic int FindFirstNonZero( int a[], int n ) { int *p; for( p = a; p < a+n && (*p) == 0; p++ ) ; return p-a; } Same as int FindFirstNonZero( int a[], int n ) { int i; for( i = 0; i < n && a[i] == 0; i++ ) ; return i; }

  39. void * void *p defines a pointer to undetermined type int j; int *p = &j; void* q = p; // no cast needed p = (int*)q ; // cast is needed

  40. NULL pointer • Special value: uninitialized pointer int *p = NULL; … if( p != NULL ) { … }

  41. NULL pointer int *p = NULL; *p = 1; Will compile… … but will lead to runtime error

  42. Debugging 101 • “Define” the bug --- reproduce it • Use debugger • Don’t panic --- think! • Divide & Conquer

More Related