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 :

Acces qui devrait provoquer un segfault mais qui ne le fait pas


Sujet :

C

  1. #1
    Membre averti Avatar de Neolex
    Homme Profil pro
    Recherche emploi Securité informatique
    Inscrit en
    Avril 2011
    Messages
    243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Recherche emploi Securité informatique

    Informations forums :
    Inscription : Avril 2011
    Messages : 243
    Points : 333
    Points
    333
    Par défaut Acces qui devrait provoquer un segfault mais qui ne le fait pas
    Bonsoir,

    J'ai crée une structure contenant un tableau de double que j'initialise un malloc , cependant lorsque je rempli un tableau de 3 cases a la case 5 par exemple , et l'affiche ensuite , je n'ai aucun segmentation fault ...
    Je n'arrive pas à comprendre pourquoi , merci de m'éclairer là dessus .

    voici ma structure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct vecteur
    {
    	double* composantes;
    	int n;
    };
    le main qui ne segfault pas... :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int main()
    {
    	vecteur v;
            initVecteur(&v,3);
            /*....*/
    	v.composantes[5]=3.0;
    	printf("%f\n",v.composantes[5]);
    	/*...*/
    	detruit(&v);
    	return 0;
    }
    Ainsi que la fonction initVecteur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void initVecteur(struct vecteur* vec,int n)
    {
    	vec->n=n;
    	vec->composantes = (double*)malloc(sizeof(double)*n);
    }
    Merci !

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Bonjour,

    Une segfault n'est pas due à une vérification de la part du langage C mais à un contrôle de limites effectuées électroniquement par ton micro-processeur, limites définies par ton système d'exploitation lorsqu'il gère ton processus. Pendant très longtemps, d'ailleurs, les PC n'étaient pas équipés de mode protégé, si bien qu'une segfault si commune de nos jours signifiait potentiellement l'écrasement et la corruption en silence de tout ce qui se trouvait en mémoire, OS compris.

    L'OS en question va attribuer un segment contigü à ton processus, qui pourra éventuellement être redimensionné si besoin. malloc() se charge ensuite de gérer au mieux son espace mais il y a de fortes chances pour que, d'une part, la taille de ce segment soit aligné sur celle d'une page, ce qui te « permet » de déborder un poil et que, d'autre part, un bloc alloué par malloc() puisse se retrouver avant un autre. Si tu dépasses, tu écris dans le bloc d'à côté. Tu corromps tes propres données mais pas celles des autres processus, et c'est tout ce qui importe à l'OS.

  3. #3
    Membre averti Avatar de Neolex
    Homme Profil pro
    Recherche emploi Securité informatique
    Inscrit en
    Avril 2011
    Messages
    243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Recherche emploi Securité informatique

    Informations forums :
    Inscription : Avril 2011
    Messages : 243
    Points : 333
    Points
    333
    Par défaut
    Bonjour ,
    D'accord merci pour ces superbes explications très claires.
    Petite question , par curiosité , ce même programme peut donc recevoir une segfault ( si j'ai bien compris lorsqu'une sigfault est affichée , le programme à reçu un signal non ? ) à l'execution sur le même ordinateur sans recompilation suivant l'état de la mémoire ? ou il faut le recompiler ? et même question sur un ordinateur différent , il peut recevoir une segfault avec et sans recompilation ?

    J'imagine que vu ce que tu m'as dit il peut segfault même sans recompilation , mais je me demande si le compilateur utilisé alloue plus de mémoire ce qu'il fait qu'il ne fera jamais de segfault et qu'il faudrait le compiler avec un autre compilateur pour qu'il segfault ?

    je ne compte pas utiliser de programme comme ça , les questions sont juste par curiosité .

    Merci beaucoup !

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Il ne « reçoit » pas une segfault, c'est lui qui la provoque. De plus, il s'agit d'un cas de figure. Ce n'est pas un objet particulier ni un message émis.

    « Segfault » est simplement l'abréviation de « Segmentation Fault », qui est elle-même le nom que l'on donne dans le monde UNIX à cet événement. Ton système d'exploitation réagit comme il l'entend à ce cas de figure, généralement en mettant fin au programme. Windows va généralement afficher un message du style « la mémoire à l'adresse xxxx ne peut pas être read ou write ». Sous UNIX, le système va effectivement envoyer le signal SIGSEGV (Segmentation Violation) au processus, ce qui aura pour effet d'y mettre fin. Techniquement, il est d'ailleurs possible d'intercepter ce signal et de rattraper la faute (la libsigsegv le fait, d'ailleurs) mais c'est la boîte de Pandore. Tout développeur sérieux te dira que ce n'est surtout pas une chose à faire sans raison valable et parfaitement justifiée.

    Petite question , par curiosité , ce même programme peut donc recevoir une segfault ( si j'ai bien compris lorsqu'une sigfault est affichée , le programme à reçu un signal non ? ) à l'execution sur le même ordinateur sans recompilation suivant l'état de la mémoire ? ou il faut le recompiler ? et même question sur un ordinateur différent , il peut recevoir une segfault avec et sans recompilation ?
    Absolument ! Avec si peu d'excursion, ce sera dur à provoquer exprès mais c'est un cas de figure qui arrive assez fréquemment. Il m'est arrivé par exemple d'avoir à porter un programme CGI-BIN web en entreprise d'un ancien Solaris vers une machine Linux, donc avec une recompilation mais sans modifier les sources. Ce programme remplissait parfaitement sa tâche depuis des années sur la machine Solaris. Mais quoi que je fasse, il plantait inexorablement à l'appel sur sa nouvelle machine. Après m'être promené un moment dans les méandres de l'application en question, j'ai fini par en conclure qu'il ne pouvait absolument pas fonctionner en l'état. Il s'est avéré qu'en fait, ce programme plantait effectivement sur la machine initiale et à chaque appel, mais APRÈS avoir généré sa page, alors qu'il crashait d'emblée sur la machine Linux.

    J'imagine que vu ce que tu m'as dit il peut segfault même sans recompilation , mais je me demande si le compilateur utilisé alloue plus de mémoire ce qu'il fait qu'il ne fera jamais de segfault et qu'il faudrait le compiler avec un autre compilateur pour qu'il segfault ?
    C'est un comportement indéfini. Même s'il y a des chances pour qu'il se répète la plupart du temps dans les mêmes conditions, il est impossible de l'affirmer à l'avance en se basant sur la simple norme. Il y a d'ailleurs un certain nombre de programmeurs fainéants (dans le mauvais sens du terme cette fois-ci) qui ont « résolu » le problème sans avoir isolé le problème initial en se contentant d'augmenter un poil la mémoire allouée et en constatant que le problème n'apparaissait plus. Outre le fait que c'est évidemment très sale, rien ne garantit que les données soient encore intègres même si le programme ne plante plus.

  5. #5
    Membre averti Avatar de Neolex
    Homme Profil pro
    Recherche emploi Securité informatique
    Inscrit en
    Avril 2011
    Messages
    243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Recherche emploi Securité informatique

    Informations forums :
    Inscription : Avril 2011
    Messages : 243
    Points : 333
    Points
    333
    Par défaut
    Bonjour,
    Merci beaucoup pour tes explications on ne peut plus claires !
    Sujet résolu

  6. #6
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 678
    Points
    13 678
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Il m'est arrivé par exemple d'avoir à porter un programme CGI-BIN web en entreprise d'un ancien Solaris vers une machine Linux, donc avec une recompilation mais sans modifier les sources. Ce programme remplissait parfaitement sa tâche depuis des années sur la machine Solaris. Mais quoi que je fasse, il plantait inexorablement à l'appel sur sa nouvelle machine. Après m'être promené un moment dans les méandres de l'application en question, j'ai fini par en conclure qu'il ne pouvait absolument pas fonctionner en l'état. Il s'est avéré qu'en fait, ce programme plantait effectivement sur la machine initiale et à chaque appel, mais APRÈS avoir généré sa page, alors qu'il crashait d'emblée sur la machine Linux.
    Je crois que j'avais déjà lu cette histoire. Elle est forte quand même

  7. #7
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Je crois que j'avais déjà lu cette histoire. Elle est forte quand même
    Oui, je radote un peu. :-) J'ai effectivement dû poster l'anecdote deux ou trois fois ici, parce que les questions posées étaient en relation avec le même problème.

    Des choses ahurissantes, on en a vu un certain nombre et je suppose tu es désormais bien placé pour en voir également. En l'occurrence, je ne me souviens plus quelle était la cause initiale mais c'est possible avec une corruption de pile, elle-même provoquée par un simple dépassement de tableau. Si le programme écrase une variable d'indice au passage avant de corrompre le cadre de pile, alors en fonction de ce qui y est écrit (par exemple des zéros), le programme peut fonctionner ou non. C'est encore plus plausible si l'indice en question est bufferisé dans un registre du processeur sur une plateforme et pas sur l'autre. Dans un cas, ça plantera tout de suite et dans l'autre, à la sortie de la boucle.

    En plus, à l'époque, c'était une vieille version d'Apache qui appelait le programme CGI en question, et Apache n'était pas capable à ce stade de détecter les segfaults de ses fils. Comme il n'y avait aucun code de retour spécial et que les headers HTTP étaient proprement émis, il n'y avait aucun moyen de savoir dans les logs que l'application avait planté.

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

Discussions similaires

  1. [PMD] règle PMD non violée, mais qui devrait l'être!
    Par lassto dans le forum Qualimétrie
    Réponses: 0
    Dernier message: 18/05/2010, 11h14
  2. Requête SQL qui a l'air simple mais qui est musclée !
    Par tamiii dans le forum Langage SQL
    Réponses: 5
    Dernier message: 04/07/2008, 17h51
  3. pas d'erreur mais ma procédure ne fait pas ce qui est demandé
    Par mennou dans le forum SQL Procédural
    Réponses: 3
    Dernier message: 15/06/2008, 17h14
  4. Déplacement qui devrait s'effectuer
    Par Hyoga dans le forum OpenGL
    Réponses: 5
    Dernier message: 22/03/2005, 14h26
  5. Une table qui existe mais qui est inconnu! ?
    Par Nino dans le forum InterBase
    Réponses: 6
    Dernier message: 13/06/2003, 12h47

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