IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Tableau : Pourquoi il n'y a pas débordement ?


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Femme Profil pro
    Enseignant
    Inscrit en
    Mai 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Par défaut Tableau : Pourquoi il n'y a pas débordement ?
    Bonjour à tous et merci pour tous les efforts que vous faites pour aider les autres.

    Depuis que je connais le langage C je sais que la déclaration int tab[2] est une déclaration d'un tableau de 2 éléments.
    Pourquoi alors le programme suivant s'exécute sans erreur de débordement (segmentation fault) ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    #include <stdio.h>
     
    int main()
    {
    	int i, tab[2];
    	for(i=0;i<3;i++)
    		tab[i]=i;
    	for(i=0;i<3;i++)
    		printf("%d | \n", tab[i]);
    }
    Merci d'avance.

  2. #2
    Membre Expert
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Par défaut
    Bonjour,
    undefined behaviour → tout peut arriver, même que ça fonctionne par hasard.

    Par exemple chez moi (linux64+gcc6.2) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    ./deb
    0 | 
    1 | 
    2 | 
    *** stack smashing detected ***: ./deb terminated
    Aborted
    Si tu as un gcc suffisamment récent essaye :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ gcc -Wall -Wextra -fsanitize=address -o deb deb.c
    $ ./deb
    =================================================================
    ==11127==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd436469b8 at pc 0x000000400a96 bp 0x7ffd43646970 sp 0x7ffd43646960
    WRITE of size 4 at 0x7ffd436469b8 thread T0
        #0 0x400a95 in main (/home/fred/Projects/tests/deb+0x400a95)
        #1 0x7fc50361b82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
        #2 0x4008f8 in _start (/home/fred/Projects/tests/deb+0x4008f8)
     
    Address 0x7ffd436469b8 is located in stack of thread T0 at offset 40 in frame
        #0 0x4009d5 in main (/home/fred/Projects/tests/deb+0x4009d5)
    ...
    ou avec un memory profiler comme valgrind :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    $ gcc -Wall -Wextra -g -o deb deb.c
    $ valgrind --leak-check=full ./deb
    ==11163== Memcheck, a memory error detector
    ==11163== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
    ==11163== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
    ==11163== Command: ./deb
    ==11163== 
    0 | 
    1 | 
    2 | 
    *** stack smashing detected ***: ./deb terminated
    ==11163== 
    ==11163== Process terminating with default action of signal 6 (SIGABRT)
    ==11163==    at 0x4E6F428: raise (raise.c:54)
    ==11163==    by 0x4E71029: abort (abort.c:89)
    ==11163==    by 0x4EB17E9: __libc_message (libc_fatal.c:175)
    ==11163==    by 0x4F5256B: __fortify_fail (fortify_fail.c:37)
    ==11163==    by 0x4F5250F: __stack_chk_fail (stack_chk_fail.c:28)
    ==11163==    by 0x400611: main (deb.c:10)
    ==11163== 
    ...
    qui te donne même l'origine de l'erreur → fonction main, ligne 10 du fichier.

  3. #3
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Je n'ai rien à ajouter aux conseils techniques de picodev qui a tout dit. Mais :

    Citation Envoyé par picodev Voir le message
    undefined behaviour → tout peut arriver
    J'insiste sur ce point, parce que c'est fondamental de comprendre ça. En C (et en C++ dans une certaine mesure), on programme sans filet : le langage ne prévoit aucun moyen de détection (et à fortiori gestion) des erreurs de programmation qui ne peuvent être interceptées à la compilation. Certes l'OS interrompra le processus s'il déconne trop à son goût mais ne fera pas de zèle.

    C'est pourquoi une segfault n'est jamais garantie (et mieux vaut qu'elle se produise), et c'est pourquoi valgrind est un outil indispensable lorsqu'il est disponible sur la plateforme cible.

  4. #4
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 254
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 254
    Par défaut
    Dit autrement, il n'y a pas de contrôle aux limites en C.
    Il faut connaitre et comprendre la gestion des variables en mémoire en C et notamment des tableaux

    int tab[2] n'est pas une variable de type tableau d'entier. En C, c'est juste la réservation d'un emplacement en mémoire pour pouvoir y stocker 2 entiers contigus et dont l'adresse mémoire est tab (correspondant à l'adresse mémoire du premier entier).

    La variable tab agit comme un pointeur. tab[0] pointe sur l'adresse mémoire du premier entier, tab[1] pointe sur l'adresse mémoire du second, mais tab[2] pointe sur l'adresse mémoire suivante qui sera considérée comme étant celle d'un entier aussi, tab[3] pointera à son tour sur l'adresse correspondant à un hypothétique entier encore après, ainsi de suite.

    Tu peux parcourir toute la mémoire ainsi sans rencontrer de message d'erreur. Tu ne rencontreras un message que lorsque tu essayera de pointer sur une zone mémoire qui n'a pas été réservée à ton process mais tu peux, d'ici là avoir lu beaucoup de bétises qui ne correspondent pas aux valeurs que tu attends.

    Évidemment la même chose est possible en écrire, en allant écrire dans les zones mémoires correspondant à d'autres variables dont tu écrasera la valeur. Imagine les plantages que ça peut causer sans forcément avoir de message d'erreur, parce que ce n'est pas en soi un dysfonctionnement en C

  5. #5
    Membre du Club
    Femme Profil pro
    Enseignant
    Inscrit en
    Mai 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Par défaut
    Un grand merci pour toutes vos réponses et éclaircissements.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 21/03/2009, 18h01
  2. Réponses: 13
    Dernier message: 27/06/2005, 14h36
  3. [BCB5][FB1.5]Pourquoi cette commande ne fonctionne pas ?
    Par Sitting Bull dans le forum Débuter
    Réponses: 1
    Dernier message: 17/11/2004, 16h27
  4. Pourquoi ce trigger ne marche pas ??
    Par Le Basque dans le forum Développement
    Réponses: 4
    Dernier message: 20/09/2004, 15h46
  5. [JLabel][HTML]pourquoi mes images s'affiche pas?!
    Par La Truffe dans le forum Composants
    Réponses: 8
    Dernier message: 29/04/2004, 11h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo