Sie sind auf Seite 1von 5

Compilation & linkage

Linkage:

Plab Tirgul 3

prog1

g++ read.o main.o


list.o o prog1

Makefiles,
Libraries,
Debugging and
Common Bugs

.o

.o

.o

read.o

main.o

list.o

Compilation:
g++ -c read.c
main.c list.c
.c

.h

read.c read.h

Compilation & linkage

If only one
file is
modified,
will we have
to recompile
all over
again?

.h

.c

list.h list.c

Makefile

Aim: Build only out-of-date files (use timestamps)


Makefile contains:

prog1

List of dependecies (no cycles)


Recovery scenario when any file is modified
.o

.o

.o

read.o

main.o

list.o

main.o: main.c list.h read.h


g++ -c main.c
Note, the tab here is
essential!

No.
The Makefile
uses the
dependencies
graph

.c
main.c

.c

.h

read.c read.h

.c
main.c

.h

.c

list.h list.c

Compilation & linkage

If read.h is
modified,
what should
be done?

In words, if any of the files {main.c, list.h, read.h}


was modified after main.o, the command
g++ -c main.c will be performed

Compilation & linkage


Makefile example:

prog1

prog1

prog1: read.o main.o list.o


g++ main.o read.o list.o o prog1

.o

We have to
recreate
only a
subset of
the files!

read.o

.o
main.o

main.o: main.c read.h list.h


g++ -c main.c

.o

read.o: read.c read.h


g++ -c read.c

list.o

.o

.o

.o

read.o

main.o

list.o

list.o: list.c list.h


g++ -c list.c
.c

.h

read.c read.h

.c
main.c

.h

.c

list.h list.c

Running make, e.g:


make prog1
make main.o

.c

.h

read.c read.h

.c
main.c

.h

.c

list.h list.c

Makefiles: macros

Makefiles: Explicit/implicit rules


We saw explicit rules so far, e.g:

Macros are similar to variables


Upper case by convention

list.o: list.c list.h


g++ -c list.c

Implicit rules (many kinds):


Example, creation by suffices.
Create .o files from .c files

Example:
OBJECTS = read.o list.o main.o
prog1: ${OBJECTS}
g++ ${OBJECTS} -o prog1

.c.o: $*.c
g++ -c

$@

$<

$* - the match without the suffix (e.g. list)


$@ - file for which the match was made (e.g. list.o)
$< - the matched dependency (e.g. list.c)

Makefiles: Explicit/implicit rules


One more example for implicit rule:
.java.class: $*.java
javac $<
Result:
For every .java file that was modified, a new
.class file will be created.

Libraries

When no explicit rule defined, an implicit rule will be


used.
not always sufficient (e.g. doesnt check .h files update)

Libraries
Library is a collection of functions, written
and compiled by someone else, that you
may want to use
Examples:
Cs standard libraries
Math library
Graphic libraries

Libraries
2 kinds of libraries:
Static libraries:
linked with your executable at compilation time
standard unix suffix: .a

Shared libraries:
loaded by the executable at run-time
standard unix suffix: .so

Libraries may be composed of many


different object files

Static libraries
Using the static library libdata.a:
g++ -o prog object1.o object2.o ldata

Creating the library data.a (2 commands):


ar rcu libdata.a data.o stack.o list.o
ranlib libdata.a

ar is like tar archive of object files


ranlib builds a symbol table for the library
to be used by the linker

static vs. shared


Static libraries pros:
Independent of the presence/location of the
libraries
Less linking overhead on run-time
Shared libraries pros:
Smaller executables
No need to re-compile executable when libraries
are changed
The same executable can run with different
libraries
Dynamic Library Loading (dll) possible

Libraries in makefile
libdata.a: ${LIBOBJECTS}
ar rcu libdata.a ${LIBOBJECTS}
ranlib libdata.a

Debugging 101
1.
2.
3.
4.

Define the bug --- reproduce it


Divide & Conquer
Use tools: debugger & more
Dont panic --- think!

OBJECTS = foo.o bar.o


CC = g++
prog: ${OBJECTS} libdata.a
${CC} ${OBJECTS} ldata o prog

Define the bug


Spend the time to find out
What is wrong?
Minimal settings that lead to the error?

Divide & Conquer


Consider possible points of failure
check each one of them separately

Reproduce the wrong behavior!


Preferably on a small example

Use Debugger
Debugger
Allow to monitor run time behavior
Check where the program crashes
Put breakpoints on specific events
Trace execution of the program

Debugger
Debugger can save a lot of time
Find why the program crash
Understand the context (call tree, value of
variables, etc.)
But
Dont be trapped into using debuggers all
the time

Other tools

Intermediate printouts
self-checking code
asserts
Memory allocation & leaks (Lecture)

Dont Panic
There a sensible explanation to the bug
Always!
Dont rush to blame the compiler/OS
Dont attribute bugs to mysterious forces

Do not try random changes to see if they


resolve the program
This will only introduce more bugs!

bug 1

Some very common bugs


(memory/pointers related)

(1)
(2)
(3)
(4)

struct Student {
int id;
char * name;
};

(5)

Student * stud =
(Student *) malloc( sizeof(Student) );
stud->id = 123456;
stud->name =
(char *) malloc(100*sizeof(char));

Memory leak!!!
if (stud != NULL) {
name is not free
free(stud);
}

(6)
(7)

(8)

bug 2
1) void myFunc() {
2)
int * x = randomNum();
3)
int result = *x; //unexpected !
4)
*x = 17; //accessing unallocated space!
5) }
6)
7) int * randomNum() {
8)
int j= srand( time(0) );
9)
return &j;
10) }

Never return a pointer of a stack-variable !

bug 3
1) void myFunc(char * input) {
2)
char * name = NULL;
3)
if (input != NULL ) {
4)
name = (char*)malloc(MAX_SIZE);
5)
strcpy(name,input);
6)
}
7)

8)
free( name );
9) }

Always use:
if (output != NULL ) {
free(output);
}

bug 4
1) void myFunc(char * input) {
2)
char * name;
3)
if (input != NULL ) {
4)
name = (char*)malloc(MAX_SIZE);
5)
strcpy(output,input);
6)
}
7)

8)
if ( name != NULL ) {
9)
free( name );
10)
}
11) }

Always initialize pointers to NULL !

Das könnte Ihnen auch gefallen