Adloun

L'adresse d'une locale, et ce qu'elle vaut trois lignes plus loin

Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 8 — Mémoire, fichiers et entrées-sorties

Énoncé

Ce programme compile. Qu'affiche-t-il ?


int* faute(void) {
    int x = 42;
    return &x;
}

void bruit(void) {
    int a = 111, b = 222, c = 333;
    printf("(bruit : %d %d %d)\n", a, b, c);
}

int main(void) {
    int* p = faute();
    printf("juste apres  : %d\n", *p);
    bruit();
    printf("apres bruit  : %d\n", *p);
    return 0;
}

Corrigé

Sortie mesurée :


juste apres  : 42
(bruit : 111 222 333)
apres bruit  : 1

Et c'est là tout le danger : la première ligne est juste. Le bloc d'activation de faute a été dépilé, mais la case n'a pas été effacée — rien ne l'efface — et personne n'est encore venu s'y installer. Le programme paraît donc fonctionner.

L'appel à bruit réutilise cette même région de pile pour ses propres locales. Après lui, *p vaut , une valeur qui ne vient de nulle part. Un bogue de cette famille survit à toutes les exécutions de mise au point et se réveille le jour où l'on insère un appel de plus.

Le compilateur l'avait dit. gcc -Wall produit :


warning: address of stack memory associated with local variable 'x' returned

C'est un avertissement qu'on ne discute pas : il n'a pas de faux positif.

Les trois corrections possibles, par ordre de préférence :

La troisième est la seule qui rende un pointeur, et c'est la seule qui déplace une charge sur l'appelant. On ne la choisit que si l'objet doit vraiment survivre.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.