Low-level programming provides a lot of power… a lot of responsibility… and a lot of bugs (often hard to find)
Example sources of problems:
Fortunately we can instruct C compiler to embed debugging symbols in the executable:
cc -g -o main main.cvalgrind) is MemcheckCode:
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int y;
if (n % 2 == 0) {
y = 2;
}
y++;
for (int i = 0; i < 10; i++) {
printf("%d\n", y + i);
}
return 0;
}Execution:
$ cc -g -o main main.c
$ echo 2 | ./main
3
4
5
6
7
8
9
10
11
12
$ echo 1 | ./main
-1976115535
-1976115534
-1976115533
-1976115532
-1976115531
-1976115530
-1976115529
-1976115528
-1976115527
-1976115526Task:
valgrind ./mainvalgrind --track-origins=yes ./mainCode:
#include <stdio.h>
#include <stdlib.h>
int main() {
int n;
scanf("%d", &n);
// alloc a NxN matrix
int **t = malloc(n * sizeof(*t));
for (int i = 0; i < n; i++)
t[i] = malloc(n * sizeof(*t[i]));
// do some matrix operations
// ...
// ...
// ...
// free the matrix
free(t);
return 0;
}Execution:
$ cc -g -o main main.c
$ echo 10 | ./mainTask:
Execute the program using Valgrind
Try different numbers typed on input
Observe section LEAK SUMMARY in Valigrind’s
output
Rerun Valgrind with open --leak-check=full
A correct code should contain this message from Valgrind:
All heap blocks were freed -- no leaks are possibleWhat should be changed in the code to achieve that?
Code:
#include <stdio.h>
int main() {
int t[4] = { 1, 2, 3, 4 };
for (unsigned int i = 3; i >= 0; i--) {
t[i] -= 1;
printf("%d\n", t[i]);
}
return 0;
}Execution:
$ cc -g -o main main.c
$ ./main
3
2
1
0
Bus error (core dumped)Task:
gdb ./mainrunbacktrace fullCode:
#include <stdio.h>
int f(int p, int r) {
if (p == r)
return p;
return f(p + 1, r - 1);
}
int main() {
int p, r;
scanf("%d %d", &p, &r);
printf("%d\n", f(p, r));
return 0;
}Execution:
$ cc -g -o main main.c
$ echo 0 6 | ./main
3
$ echo 0 5 | ./main
Segmentation fault (core dumped)Task:
run (remember that the program waits
for two integers for scanf so write 0 5 and
press enter after executing run in GDB)backtrace fullif statement to make it work?Code:
#include <stdio.h>
#include <stdlib.h>
void f(char *p, int n) {
for (int i = 0; i < n; i++) {
p[i] += 1;
}
}
int main() {
char buffer[8] = "abcdefgh";
int length = sizeof(buffer);
f(buffer, length + 1);
return 0;
}Execution:
$ cc -g -o main main.c
$ ./main
*** stack smashing detected ***: terminated
Interrupted (core dumped)Task:
Try executing it under Valgrind
Try compiling it with:
$ cc -g -fsanitize=address -o main main.cDoes it help to find the source of problem?
If not, execute the program under GDB
You can use break to set a breakpoint in desired
code location
You can use step instead of next to go
into a function call
The code was supposed to modify abcdefgh into
bcdefghi. Can you fix the error to achieve that?
xyz, the result was
abc”)