Soit le code suivant:
// inf104.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *add_suffix(char *filename) {
char *result = (char *) malloc(strlen(filename) + 4); // L1
strcpy(result, filename); // L2
strcpy(result + strlen(filename), ".exe"); // L3
free(filename);
return result;
}
int main(int argc, char *argv[]) {
char filename[] = "main";
int x = 0;
printf("filename = %s\n", add_suffix(filename));
}
Ce programme échoue à s’exécuter correctement. On va utiliser le debugger gdb
gcc -Wall -g -c inf104.c
gcc -g inf104.o -o inf104
gdb ./inf104
// exécute le programme ./inf104 supervisé par le debugger gdb
(gdb) break main
// demande l’arrêt de l’exécution à l’appel de la fonction main
(gdb) run
// lance l’exécution sans paramètre, comme si on exécutait ./inf104. On peut donner des arguments à l’exécution comme dans ./inf104 1 2 3 en faisant run 1 2 3
Breakpoint 1, main (argc=1, argv=0x7ffeefbff210) at inf104.c:14
14 char filename[] = “main”;
(gdb) next
// exécute l’instruction suivante
15 int x = 0;
(gdb) n
// exécute l’instruction suivante. n est un raccourci de next
16 printf(“filename = %s\n”, add_suffix(filename));
(gdb) p &filename
$2 = (char (*)[5]) 0x7ffeefbff1e7
(gdb) p &x
$3 = (int *) 0x7ffeefbff1ec
// Remarquez que les adresses de filename et result sont proches et dans la pile.
(gdb) b add_suffix
// b est un raccourci de break. On s’arrête aussi en add_suffix désormais.
Breakpoint 2 at 0x100000e30: file inf104.c, line 6.
(gdb) continue
// On continue l’exécution, jusqu’au prochain point d’arrêt (breakpoint)
Continuing.
Breakpoint 2, add_suffix (filename=0x7ffeefbff1e7 “main”) at inf104.c:6
6 char *result = (char *) malloc(strlen(filename) + 4); // L1
(gdb) next
7 strcpy(result, filename); // L2
(gdb) p result
$4 = 0x100400000 “”
// Notez que result est alloué dans le tas à une adresse très différente de x et de filename (ie dans la pile)
(gdb) next
8 strcpy(result + strlen(filename), “.exe”); // L3
(gdb) n
9 free(filename);
(gdb) n
inf104(76288,0x1000a55c0) malloc: *** error for object 0x7ffeefbff1e7: pointer being freed was not allocated
inf104(76288,0x1000a55c0) malloc: *** set a breakpoint in malloc_error_break to debug
Program received signal SIGABRT, Aborted.
Donc le problème survient dans free. L’erreur indique “pointer being freed was not allocated”
En effet, filename d’adresse 0x7ffeefbff1e7 a été alloué sur la pile.