Setting up C/C++ compiler
If you are using an older browser, and this site does not work, you may try an older version of this site.
I will be using GNU C Compiler (GCC) to compile codes in a Linux computer. You
can install GCC in Ubuntu/
apt install gcc
Command to compile:
gcc filename.c
# linking math lib
gcc filename.c -lm
# show all compiler warnings
gcc -Wall filename.c
g++ filename.cpp
# compile with specific standard (might require for latest language features)
g++ -std=c++17 filename.cpp
g++ -std=c++2a filename.cpp
This would produce executable with default name a.out. You can specify the
executable name by using the -o flag:
gcc filename.c -o program_name
For complex programs, you can use -g flag to generate debugging information.
-O flag can be used to optimize the executable file (-O2, -O3 denotes
various levels of optimization).
Compiler (GCC/-Wall, -Wextra, -Wpedantic,
-Wunused.
Makefile
For large/
CC=g++
CFLAGS=-O3 -Wall
# By default the left-hand-side of the first dependency is what you
# get if you just type `make` with no arguments, in this case `make all`
all: hello
# commands must be indented with TAB not spaces
# If you need to repair a Makefile that uses spaces, one way of converting
# leading spaces into TABs is to use the unexpand program:
# mv Makefile Makefile.old
# unexpand Makefile.old > Makefile
# $@ = target
# $^ = dependencies
# ${CC} -o hello hello.o
hello: hello.o
$(CC) $(CFLAGS) -o $@ $^
# ${CC} -c 00-hello-world.cpp -o hello.o
# $(CC) $(CFLAGS) -o $@ -c $^
hello.o: 00-hello-world.cpp
$(CC) $(CFLAGS) -o $@ -c $^
# The $(RM) variable is predefined to "rm -f"
clean:
$(RM) hello *.o
A makefile is consists of a set of rules. A rule consists of a target, a list of
prerequisites, and a command. In the above example, we have several rules:
all, hello, hello.o, and clean. In case of all, we have prerequisite
hello, while there is no command. In case of hello, prerequisite is hello.o
and rule is: ${CC} -o hello hello.o and so on. If we run make without any
argument, the first rule will run, which is in this case all. We can run
another rule, we can run it by providing its name, e.g., make clean. Later we
will see use of more complex makefile.
Debugging
sudo apt update && sudo apt install gdb
We can use gdb to debug our program. We can embeed debugging information to
our code by using -g or -g3 flag. It might be helpful also to disable
optimizations with -O0 while debugging. We compile the program:
gcc -g -O0 -Wall filename.c -o filename.o
Using gdb:
gdb filename.o
Useful gdb commands:
| Commands | Description |
|---|---|
break/b line-number | create breakpoint at specific line |
break filename:line-number | create breakpoint at specific line and file |
| run/r | run program |
| c | continue execution |
| next | execute next line |
| step/s | execute next line or step into function |
| quit/q | quit gdb |
| print expression | print current value of a specified expression |
| help [command] | in-program help |
| bt | print the stack trace |
clear line-number | clear break point |
clear filename:line-number | clear break point in a specific file and line |
| info/i break/b | list all break points |
del breakpoint Num | delete a break point |
del start-br-pt-end-br-pt | delete break points from start-breakpoint-Num to end-breakpoint-Num |
Cppcheck
Sometimes I will be using cppcheck to debug codes as well.
apt install cppcheck
cppcheck --enable=all filename.cpp
Valgrind
Install valgrind in Ubuntu/Debian:
apt install valgrind
Valgrind is a memory profiling tool (includes memcheck, cachegrind, callgrind, etc). First compile your program with debug flag:
gcc -g filename.c
valgrind ./a.out
valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes ./a.out
Valgrind can also detect:
- invalid pointer use
- use of uninitialized variables
- double frees
Valgrind does not check bounds on statically allocated arrays.