View
233
Download
0
Embed Size (px)
Citation preview
Plab – Tirgul 3
Makefiles,Libraries,
Debugging andCommon Bugs
Compilation & linkage
.h
read.h
.c
read.c
.c
main.c
.c
list.c
.h
list.h
prog1Linkage:
g++ read.o main.o list.o –o prog1
.o
main.o
.o
list.o
.o
read.o
Compilation:
g++ -c read.c main.c list.c
Compilation & linkage
.h
read.h
.c
read.c
.c
main.c
.c
list.c
.h
list.h
prog1
.o
main.o
.o
list.o
.o
read.o
•If only one file is modified, will we have to recompile all over again?
•No.
The Makefile uses the dependencies graph
• Aim: Build only out-of-date files (use timestamps)• Makefile contains:
– List of dependecies (no cycles)– “Recovery” scenario when any file is modified
main.o: main.c list.h read.hg++ -c main.c
• 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
Makefile
Note, the tab here is essential!
Compilation & linkage
.h
read.h
.c
read.c
.c
main.c
.c
list.c
.h
list.h
prog1
.o
main.o
.o
list.o
.o
read.o
•If read.h is modified, what should be done?
•We have to recreate only a subset of the files!
Compilation & linkage
.h
read.h
.c
read.c
.c
main.c
.c
list.c
.h
list.h
prog1
.o
main.o
.o
list.o
.o
read.o
Makefile example:
prog1: read.o main.o list.og++ main.o read.o list.o –o prog1
main.o: main.c read.h list.hg++ -c main.c
read.o: read.c read.hg++ -c read.c
list.o: list.c list.hg++ -c list.c
Running make, e.g:make prog1make main.o
Makefiles: macros
• Macros are similar to variables– Upper case by convention
• Example:
OBJECTS = read.o list.o main.oprog1: ${OBJECTS}
g++ ${OBJECTS} -o prog1
Makefiles: Explicit/implicit rules• We saw “explicit rules” so far, e.g:
list.o: list.c list.hg++ -c list.c
• Implicit rules (many kinds):– Example, creation by suffices.
Create “.o” files from “.c” files
.c.o: $*.cg++ -c –o $@ $<
$* - 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: $*.javajavac $<
Result:For every “.java” file that was modified, a new “.class” file will be created.
• When no explicit rule defined, an implicit rule will be used.
– not always sufficient (e.g. doesn’t check .h files update)
Libraries
Libraries• Library is a collection of functions, written
and compiled by someone else, that you may want to use
• Examples:– C’s standard libraries– Math library– Graphic libraries
• Libraries may be composed of many different object files
Libraries2 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
Static librariesUsing 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 makefilelibdata.a: ${LIBOBJECTS}
ar rcu libdata.a ${LIBOBJECTS}
ranlib libdata.a
OBJECTS = foo.o bar.o
CC = g++
prog: ${OBJECTS} libdata.a
${CC} ${OBJECTS} –ldata –o prog
Debugging 101
1. “Define” the bug --- reproduce it
2. Divide & Conquer
3. Use tools: debugger & more
4. Don’t panic --- think!
Define the bug
Spend the time to find out
• What is wrong?
• Minimal settings that lead to the error?
Reproduce the wrong behavior!
• Preferably on a small example
Divide & Conquer
Consider possible points of failure– check each one of them separately
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…
• Don’t be trapped into using debuggers all the time
Other tools
• Intermediate printouts
• self-checking code
• asserts
• Memory allocation & leaks (Lecture)
Don’t Panic
There a sensible explanation to the bug– Always!– Don’t rush to blame the compiler/OS– Don’t attribute bugs to mysterious forces
Do not try random changes to see if they resolve the program– This will only introduce more bugs!
Some very common bugs(memory/pointers related)
bug 1(1) struct Student {(2) int id;(3) char * name;(4) };
(5) Student * stud = (Student *)
malloc( sizeof(Student) );(6) stud->id = 123456;(7) stud->name =
(char *) malloc(100*sizeof(char));…
(8) if (stud != NULL) {free(stud);
}
Memory leak!!!“name” is not free
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 41) 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 !