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 :

Pourquoi l'application de segfault pas


Sujet :

C++

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2016
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2016
    Messages : 4
    Points : 0
    Points
    0
    Par défaut Pourquoi l'application de segfault pas
    Bonjour à tous,
    Si vous avez du temps à m'accorder - je vous expose mon tracas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include <vector>
    #include <iostream>
    using namespace std;
    int main(){
     vector<int> Entier(1, 5);
     Entier[0] = 6;
      Entier.erase(Entier.begin());
     Entier[0] = 7;
     std::cout << Entier[0] << endl;
     std::cout << Entier.size() << endl;
     return 0;
    }
    J'ai cherché des solutions sur Internet, auprès d'amis pour mieux comprendre (Car j'apprends le C++).
    Je n'ai pas compris pourquoi à la ligne "std::cout << Entier[0] << endl;" L'élement n'est pas effacé alors que j'ai utiliser la fonction Erase bien que la taille m'indique qu'elle est de 0.

  2. #2
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    1. Le segfault n'est jamais garanti lors d'un accès non-autorisé, ce qui l'est c'est l'obtention d'un comportement indéterminé.
    2. Compilé avec les optimisations activées (release), l'opérateur [] ne fait pas de bounds checking. Je ne suis même pas sûr qu'il en fasse en debug d'ailleurs (de mémoire c'est la différence avec at()).
    3. Le bloc mémoire réservé par cet objet vecteur est toujours alloué après l'effacement de l'élément. Tu n'auras donc probablement jamais de segfault avec ce code.

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 630
    Points : 30 694
    Points
    30 694
    Par défaut
    Salut,

    Tu viens de faire l'expérience de toute la différence qu'il y a entre la capacité et la taille d'un tableau

    Sa capacité, c'est le nombre d'éléments qu'il peut contenir avant de devoir demander un espace supplémentaire pour pouvoir placer l'élément suivant, alors que la taille correspond au nombre d'éléments qu'il contient effectivement.

    Il faut en effet savoir plusieurs choses à propos de la classe std::vector :

    Chaque fois qu'on ajoute un élément en plus que ce que sa capacité autorise, il va augmenter la capacité, mais pas de manière "rectiligne" : si tu ajoute quinze éléments l'un à la suite de l'autre, il n'augmentera sans doute pas quinze fois sa capacité de 1 mais il suivra plutôt une évolution "logarithmique" (ou peu s'en faut), en doublant (à peu de choses près) sa capacité à chaque fois.

    Ainsi, si tu veux ajouter 15 éléments dans un tableau qui est vide à l'origine, il y a des chances que sa capacité suive l'évolution : 0 (capacité de départ), 1, 2, 4, 8, 16 et qu'elle passera directement à ... 32 lorsque tu voudras ajouter le 17eme élément.

    De plus, la suppression d'un élément ne provoque pas de diminution de la capacité : tous les éléments qui suivent celui qui est retiré sont "décalés d'une case" vers le "début du tableau"; l'élément retiré est "relégué à la dernière place" et il n'y a que le "pointeur sur le dernier élément" est reculé d'une place.

    Si bien que, si tu as 16 éléments dans un tableau, il est fort possible que la taille et la capacité soient identiques. Mais, si tu supprimes un de ces éléments, seule la taille passera à 15, alors que la capacité sera toujours égale à ... 16, ce qui signifie que cette "16eme case" a beau ne pas être utilsée pour "représenter un élément du tableau", elle fait quand même toujours partie de l'espace mémoire dont le tableau dispose pour mettre des éléments.

    Tu n'est, normalement, pas sensé accéder à cette case mémoire "inutilisée" : que ce soit au travers d'une boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for(size_t i=0;i<tab.size();++i)
    ou au travers d'une boucle utilisant les itérateur fonctionnant "tant que l'itérateur courant n'est pas égal à end()", toute les logiques tendront à... te faire arrêter avant d'y accéder.

    Mais, comme il n'y a aucun contrôle sur la validité des indices que tu fournis à l'opérateur [], il se peut parfaitement que tu arrives malgré tout à y accéder en indiquant (en dur) l'indice en question. Et le système d'exploitation n'y verra aucune objection, vu que, pour lui, tu accède encore à une adresse mémoire qui apparatient au tableau

    Ensuite, il faut savoir qu'un accès en lecture occasionnera rarement une erreur de segmentation, surtout lorsque l'on essaye de "lire" une donnée de type primitif (comme l'est le type int).

    L'erreur de segmentation survient généralement quand on interprète mal la valeur qui se trouve à un endroit donné en mémoire. Par exemple, en croyant que l'on a affaire à l'adresse mémoire représentée par un pointeur, et que l'on essaye de déréférencer cette valeur ( ex : ptr->X) ou lorsque l'on essaye de modifier la valeur en question, par exemple, en introduisant une valeur représentant une adresse à l'emplacement prévu pour contenir un nombre équivalent de caractères. Et encore : il est tout à fait possible que cela ne fasse que "mettre en place" les conditions pour une erreur de segmentation ... qui surviendra plus tard.

    Enfin, il faut savoir que le système d'exploitation peut en faire à peu près à sa tête, tant qu'il fournit un adresse mémoire qui permet, effectivement, de représenter le nombre d'éléments qu'on lui a indiqué.

    C'est à dire que, si tu lui demande un espace mémoire de, mettons 20 bytes, il peut tout aussi bien te fournir 20 bytes qui sont "entourés" par des adresses mémoires utilisées que 20 bytes qui sont suivis de ... 150Mb de mémoire inutilisés.

    Et tant que tu n'ira pas "chipoter" à une case de mémoire qui est utilisée pour autre chose, il pourrait encore tout à fait te laisser faire

  4. #4
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2016
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2016
    Messages : 4
    Points : 0
    Points
    0
    Par défaut
    Excellent explication! Je vous remercie pour votre aide, je comprend mieux!

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

Discussions similaires

  1. [Déploiement] Pourquoi mon application ne fonctionne pas sur tous les postes ?
    Par Willthelegend dans le forum Windows Presentation Foundation
    Réponses: 3
    Dernier message: 08/09/2008, 21h34
  2. Réponses: 1
    Dernier message: 30/08/2006, 20h00
  3. Pourquoi ce trigger ne marche pas ??
    Par Le Basque dans le forum Développement
    Réponses: 4
    Dernier message: 20/09/2004, 16h46
  4. Une application Dialog based pas rectangulaire....
    Par feed_our_vision dans le forum MFC
    Réponses: 2
    Dernier message: 14/06/2004, 11h10
  5. [JLabel][HTML]pourquoi mes images s'affiche pas?!
    Par La Truffe dans le forum Composants
    Réponses: 8
    Dernier message: 29/04/2004, 12h23

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