compilation / pointers debugging 101

42
. Compilation / Pointers Debugging 101

Upload: brit

Post on 13-Jan-2016

35 views

Category:

Documents


0 download

DESCRIPTION

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. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Compilation / Pointers Debugging 101

.

Compilation / PointersDebugging 101

Page 2: Compilation / Pointers Debugging 101

Compilation in C/C++

hello.c

Preprocessor Compiler

stdio.h

tmpXQ.i(C code)

hello.o(object

file)

Page 3: Compilation / Pointers Debugging 101

Preprocesser

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

Page 4: Compilation / Pointers Debugging 101

#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)

Page 5: Compilation / Pointers Debugging 101

Modules & Header files

Complex.c

struct Complex { double _real, _imag;};Complex addComplex(Complex, Complex);Complex subComplex(Complex, Complex);...

complex.h

#include <math.h>#include “complex.h”

// implementationComplex addComplex(Complex a, Complex b){ …

complex.c

#include “complex.h”int main(){ Complex c; …

MyProg.c

Page 6: Compilation / Pointers Debugging 101

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

Page 7: Compilation / Pointers Debugging 101

#define directive

#define FOO 1

int x = FOO;

is equivalent to

int x = 1;

Page 8: Compilation / Pointers Debugging 101

#define with arguments

#define square(x) x*x

b = square(a);

is the same as

b = a*a;

Page 9: Compilation / Pointers Debugging 101

#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;

Page 10: Compilation / Pointers Debugging 101

#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)

Page 11: Compilation / Pointers Debugging 101

#if directive

Allows to have conditional compilation#if defined(DEBUG)

// compiled only when DEBUG exists

printf(“X = %d\n”, X);

#endif

Page 12: Compilation / Pointers Debugging 101

#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'

Page 13: Compilation / Pointers Debugging 101

#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

Page 14: Compilation / Pointers Debugging 101

Preprocessor

We can test what the preprocessor does

> gcc –E hello.c

will print the C code after running preprocess

Page 15: Compilation / Pointers Debugging 101

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, thenassertion "x >= 0" failed: file "Sqrt.c", line 7

<exception>

The exception allows to catch the event in the debugger

Page 16: Compilation / Pointers Debugging 101

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?

Page 17: Compilation / Pointers Debugging 101

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

Page 18: Compilation / Pointers Debugging 101

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

Page 19: Compilation / Pointers Debugging 101

Linking

Combines several object files into an executable file No unresolved references

Main

PreprocessorCompiler

Complex.c Complex.o

Main.c Main.o

Linker

libc.a

Page 20: Compilation / Pointers Debugging 101

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.ofoo.o(.text+0x0):foo.c: multiple definition of `foo'

Main.o(.text+0x38):Main.c: first defined here

Page 21: Compilation / Pointers Debugging 101

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)

Page 22: Compilation / Pointers Debugging 101

Memory

int main()

{

char c;

int i,j;

double x;

c i j x

Page 23: Compilation / Pointers Debugging 101

Arrays

Defines a block of consecutive cellsint main()

{

int i;

int a[4];

i a[0] a[1] a[2] a[3]

Page 24: Compilation / Pointers Debugging 101

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…

Page 25: Compilation / Pointers Debugging 101

Arrays

C does not provide array operations int a[4];

int b[4];

… a = b; // illegal

if( a == b ) // illegal

Page 26: Compilation / Pointers Debugging 101

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

Page 27: Compilation / Pointers Debugging 101

Pointersint 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

Page 28: Compilation / Pointers Debugging 101

Pointersint main()

{

int i,j;

int *x; // x points to an integer

i = 1;

x = &i;

j = *x;

x = &j;

(*x) = 3;i j x

10x0100

0x0100

Page 29: Compilation / Pointers Debugging 101

Pointersint main()

{

int i,j;

int *x; // x points to an integer

i = 1;

x = &i;

j = *x;

x = &j;

(*x) = 3;i j x

10x0100

0x01001

Page 30: Compilation / Pointers Debugging 101

Pointersint main()

{

int i,j;

int *x; // x points to an integer

i = 1;

x = &i;

j = *x;

x = &j;

(*x) = 3;i j x

10x0100

0x01041

Page 31: Compilation / Pointers Debugging 101

Pointersint main()

{

int i,j;

int *x; // x points to an integer

i = 1;

x = &i;

j = *x;

x = &j;

(*x) = 3;i j x

10x0100

0x01043

Page 32: Compilation / Pointers Debugging 101

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

Page 33: Compilation / Pointers Debugging 101

Example – the swap functionDoes 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…

Page 34: Compilation / Pointers Debugging 101

Pointers & Arrays

int *p;

int a[4];

p = &a[0];

*(p+1) = 1; // assignment to a[1]!

p a[1] a[2] a[3]a[0]

Page 35: Compilation / Pointers Debugging 101

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

Page 36: Compilation / Pointers Debugging 101

Pointers & Arrays

int foo( int *p );

andint foo( int a[] );

Are declaring the same interface In both cases, a pointer to int is being passed

to the function foo

Page 37: Compilation / Pointers Debugging 101

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[1] a[2] a[3]a[0]

q p

Page 38: Compilation / Pointers Debugging 101

Pointer arithmeticint 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;

}

Page 39: Compilation / Pointers Debugging 101

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

Page 40: Compilation / Pointers Debugging 101

NULL pointer

Special value: uninitialized pointer

int *p = NULL;

if( p != NULL )

{

}

Page 41: Compilation / Pointers Debugging 101

NULL pointer

int *p = NULL;

*p = 1;

Will compile…

… but will lead to runtime error

Page 42: Compilation / Pointers Debugging 101

Debugging 101

1. “Define” the bug --- reproduce it

2. Use debugger

3. Don’t panic --- think!

4. Divide & Conquer