Utilisation de gdb

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.