foo: foo.cpp g++ -o foo foo.cpp debugfoo: foo.cpp g++ -g -o debugfoo foo.cppTasks:
Makefiles automate repetitive tasks, such as compiling C++ source files. Makefiles are collections of rules, dependences and actions. The user activates a rule, which activates other necessary rules (depending on the dependences) until a particular set of actions is performed.
make
activates the first rule: foo if foo.cpp has changed then it is re-compiled into foo
make foo
activates the given rule: foo if foo.cpp has changed then it is re-compiled into foo
make debugfoo
activates the given rule: debugfoo if debugfoo.cpp has changed then it is re-compiled into foo
Include four rules:
Note: make sure you use the g++ compiler.
all: square fileio squaregdb fileiogdb square: square.cpp g++ -lm square.cpp -o square squaregdb: square.cpp g++ -g -lm square.cpp -o squaregdb fileio: fileio.cpp g++ fileio.cpp -o fileio fileiogdb: fileio.cpp g++ -g fileio.cpp -o fileiogdb clean: rm square fileio squaregdb fileiogdb
Even after getting a program to compile successfully, it is fairly rare to have a large or medium-sized program run perfectly the first time it is executed. Usually the programmer must spend some further time running and debugging the code.
It allow us to run a program part way, then interrupt it and check the value of certain variables, possibly watching what happens to the value of those variables over the next several instructions, etc. This will help reveal what is going wrong with the program.
gdb
Note: You can get online help from inside gdb by entering the command help from the (gdb) prompt.
% gdb GDB is free software and you are welcome to distribute copies of it under certain conditions; type "show copying" to see the conditions. There is absolutely no warranty for GDB; type "show warranty" for details. GDB 4.16 (alpha-dec-osf4.0), Copyright 1996 Free Software Foundation, Inc. (gdb) file squaregdb Reading symbols from squaregdb...done. (gdb) set args 1 2 3 4 5 (gdb) break main Breakpoint 1 at 0x12000a358: file square.cpp, line 5. (gdb) list 1 #include2 #include 3 #include 4 void main(int argc, char* argv[]) { 5 if (argc == 1) 6 cout << "No args. Terminating." << endl; 7 else { 8 for (int index=1; index < argc; index++) { 9 cout << "arg[" << index << "]: square = " 10 << pow(atoi(argv[index]),2) << endl; (gdb) list 11 } 12 } 13 } 14 (gdb) break 9 Breakpoint 2 at 0x12000a3c0: file square.cpp, line 9. (gdb) r Starting program: /postgrad/postgrad/59502/sci-jjh/cp1300/w7/squaregdb 1 2 3 4 5 Breakpoint 1, main (argc=6, argv=0x11ffffb08) at square.cpp:5 5 if (argc == 1) (gdb) print argc $1 = 6 (gdb) print argv [0] $2 = 0x11ffffc48 "/postgrad/postgrad/59502/sci-jjh/cp1300/w7/squaregdb" (gdb) s 8 for (int index=1; index < argc; index++) { (gdb) print index $3 = 1 (gdb) s 10 << pow(atoi(argv[index]),2) << endl; (gdb) s ostream::operator<< (this=0x140000038, s=0x1400007d0 "arg[") at iostream.cc:756 iostream.cc:756: No such file or directory. (gdb) c Continuing. arg[1]: square = 1 Breakpoint 2, main (argc=6, argv=0x11ffffb08) at square.cc:10 10 << pow(atoi(argv[index]),2) << endl; (gdb) print index $4 = 2 (gdb) c Continuing. arg[2]: square = 4 Breakpoint 2, main (argc=6, argv=0x11ffffb08) at square.cpp:10 10 << pow(atoi(argv[index]),2) << endl; (gdb) print index $5 = 3 (gdb) c Continuing. arg[3]: square = 9 Breakpoint 2, main (argc=6, argv=0x11ffffb08) at square.cpp:10 10 << pow(atoi(argv[index]),2) << endl; (gdb) print index $6 = 4 (gdb) c Continuing. arg[4]: square = 16 Breakpoint 2, main (argc=6, argv=0x11ffffb08) at square.cpp:10 10 << pow(atoi(argv[index]),2) << endl; (gdb) print index $7 = 5 (gdb) c Continuing. arg[5]: square = 25 Program exited normally. (gdb) set args (gdb) show args Arguments to give program being debugged when it is started is "". (gdb) r Starting program: /postgrad/postgrad/59502/sci-jjh/cp1300/w7/squaregdb Breakpoint 1, main (argc=1, argv=0x11ffffb28) at square.cpp:5 5 if (argc == 1) (gdb) print argc $9 = 1 (gdb) s 6 cout << "No args. Terminating." << endl; (gdb) s ostream::operator<< (this=0x140000038, s=0x1400007b8 "No args. Terminating.") at iostream.cc:756 iostream.cc:756: No such file or directory. (gdb) c Continuing. No args. Terminating. Program exited normally. (gdb) q
Take the following code called "fishy.cpp" and compile it for profiling:
// The three Fishermen problem /* How many fish overall do three fishermen have if: * one leaves and takes his share (3 equal shares with 1 remaining fish) * another leaves and takes his share (of the remaining fish, computed as above) * the last one leaves and takes his share (of the leftover fish, computed as above) */ #include <iostream.h> #include <stdlib.h> bool calcShare(int, int&); int calcFish(int); int main(int argc, char** argv) { int maxValue; if (argc == 2 && (maxValue = atoi(argv[1])) != 0) { int smallestShare, middleShare, overallShare; for (smallestShare = 1; smallestShare < maxValue; smallestShare++) { cout << "Trying smallest share = " << smallestShare; if (calcShare(smallestShare,middleShare)) { cout << '.'; if (calcShare(middleShare,overallShare)) { cout << " Overall Number of Fish = " << calcFish(overallShare); } } cout << endl; } } else cout << "Usage: fishy <n>" << endl << "<n> is largest number to try" << endl; return 0; } bool calcShare(int smaller, int& larger) { larger = calcFish(smaller); if (larger % 2 == 0) { larger /= 2; return true; } else return false; } int calcFish(int smaller) { return (3*smaller + 1); }
% g++ -pg fishy.cpp -o fishy
Run the executable and generate a profiling report (execute it as: "fishy 1000").
Note that the profiling wont have much time to sample; larger
more complex programs will provide more numeric profile information.
% gprof -b fishy
granularity: each sample hit covers 0 byte(s) no time propagated called/total parents index %time self descendents called+self name index called/total children 0.00 0.00 250/1749 main [3] 0.00 0.00 1499/1749 calcShare__FiRi [2] [1] 0.0 0.00 0.00 1749 calcFish__Fi [1] ----------------------------------------------- 0.00 0.00 1499/1499 main [3] [2] 0.0 0.00 0.00 1499 calcShare__FiRi [2] 0.00 0.00 1499/1749 calcFish__Fi [1] ----------------------------------------------- 0.00 0.00 1/1 __start [49] [3] 0.0 0.00 0.00 1 main [3] 0.00 0.00 1499/1499 calcShare__FiRi [2] 0.00 0.00 250/1749 calcFish__Fi [1] ----------------------------------------------- 0.00 0.00 1/1 __start [49] [3] 0.0 0.00 0.00 1 main [3] 0.00 0.00 1499/1499 calcShare__FiRi [2] 0.00 0.00 250/1749 calcFish__Fi [1] ----------------------------------------------- ^L granularity: each sample hit covers 0 byte(s) no time accumulated % cumulative self self total time seconds seconds calls ms/call ms/call name 0.0 0.00 0.00 1749 0.00 0.00 calcFish__Fi [1] 0.0 0.00 0.00 1499 0.00 0.00 calcShare__FiRi [2] 0.0 0.00 0.00 1 0.00 0.00 main [3] ^L Index by function name [1] calcFish__Fi [2] calcShare__FiRi [3] main
Use "gprof -b fishy | less" for a page-at-atime output, or:
gprof -b fishy > results.txt
less results.txt
g++ -S fishy.cpp
produces fishy.s
In "man gcc" there is an option "-v" that lists the stages of compilation and the commands used; this also applies to g++. Using "g++ -v fishy.cpp" will list the compilation commands:
Reading specs from /usr/local/lib/gcc-lib/alphaev6-dec-osf4.0f/2.95.2/specs gcc version 2.95.2 19991024 (release) /usr/local/lib/gcc-lib/alphaev6-dec-osf4.0f/2.95.2/cpp -lang-c++ -v -D__GNUC__= 2 -D__GNUG__=2 -D__GNUC_MINOR__=95 -D__cplusplus -Dunix -D__osf__ -D_LONGLONG -D SYSTYPE_BSD -D_SYSTYPE_BSD -D__unix__ -D__osf__ -D_LONGLONG -D__SYSTYPE_BSD__ -D _SYSTYPE_BSD -D__unix -D__SYSTYPE_BSD -Asystem(unix) -Asystem(xpg4) -D__EXCEPTIO NS -D__LANGUAGE_C__ -D__LANGUAGE_C -DLANGUAGE_C -Acpu(alpha) -Amachine(alpha) -D __alpha -D__alpha__ -D__alpha_ev6__ -Acpu(ev6) -D__alpha_bwx__ -Acpu(bwx) -D__al pha_max__ -Acpu(max) -D__alpha_fix__ -Acpu(fix) fishy.cpp /tmp/cc6ftETm.ii GNU CPP version 2.95.2 19991024 (release) pha_max__ -Acpu(max) -D__alpha_fix__ -Acpu(fix) fishy.cpp /tmp/cc6ftETm.ii GNU CPP version 2.95.2 19991024 (release) #include "..." search starts here: #include <...> search starts here: /usr/local/lib/gcc-lib/alphaev6-dec-osf4.0f/2.95.2/../../../../include/g++-3 /usr/local/include /usr/local/lib/gcc-lib/alphaev6-dec-osf4.0f/2.95.2/../../../../alphaev6-dec-osf 4.0f/include /usr/local/lib/gcc-lib/alphaev6-dec-osf4.0f/2.95.2/include /usr/include End of search list. The following default directories have been omitted from the search path: End of omitted list. GNU C++ version 2.95.2 19991024 (release) (alphaev6-dec-osf4.0f) compiled by GNU C version 2.95.2 19991024 (release).ase) (alphaev6-dec-osf4.0f) compiled by GNU as -g -nocpp -O0 -o /tmp/ccpdZIhN.o /tmp/ccATKnrO.s /usr/local/lib/gcc-lib/alphaev6-dec-osf4.0f/2.95.2/mips-tfile -v -o /tmp/ccpdZI hN.o /tmp/ccATKnrO.s mips-tfile version 2.95.2 19991024 (release) /usr/local/lib/gcc-lib/alphaev6-dec-osf4.0f/2.95.2/collect2 -G 8 -O1 -call_shar ed /usr/lib/cmplrs/cc/crt0.o -L/usr/local/lib/gcc-lib/alphaev6-dec-osf4.0f/2.95. 2 -L/usr/lib/cmplrs/cc -L/usr/local/lib /tmp/ccpdZIhN.o -lstdc++ -lm -lgcc -lc - lgcc
g++ uses a series of temporary files in /tmp for the intermediate assembly code, object code, etc.
We can use the "as" command as above to compile "fishy.s"
into the object file "fishy.o"
(include all the same parameters...)
There is no need to apply the the "mips-tfile" command (this is optional, it setups debugging info)
Then use ld (which, is the same sort of thing as the
"collect2" linker command) to produce the final
executable!
Something like (long lines are wrapped around):
% g++ -S fishy.cpp % as -g -nocpp -O0 -o fishy.o fishy.s % ld -G 8 -call_shared /usr/lib/cmplrs/cc/crt0.o -L/usr/local/lib/gcc-lib/alphae v6-dec-osf4.0f/2.95.2 -L/usr/lib/cmplrs/cc -L/usr/local/lib fishy.o -lstdc++ -lm -lgcc -lc -o fishy % fishy Usage: fishy <n> <n> is largest number to try %