74 votes

Quel est le moyen le plus simple conforme de produire un Segfault en C?

Je pense que la question, dit-il. Un exemple en couvrant la plupart des normes de C89-C11 serait utile. J'ai bien de celui-ci, mais je suppose que c'est juste un comportement indéterminé:

#include <stdio.h>

int main( int argc, char* argv[] )
{
  const char *s = NULL;
  printf( "%c\n", s[0] );
  return 0;
}

EDIT:

Comme certaines voix a demandé des précisions: je voulais avoir un programme avec une habitude erreur de programmation (le plus simple que je pouvais penser était une erreur de segmentation), qui est garanti (en standard) pour annuler. C'est un peu différent pour le minimum d'erreur de segmentation question, qui ne se soucient pas de cette assurance.

115voto

msam Points 2883

raise() peut être utilisé pour générer une erreur de segmentation:

 raise(SIGSEGV);
 

77voto

Shafik Yaghmour Points 42198

Une erreur de segmentation est une mise en œuvre défini le comportement de la norme ne définit pas la façon dont la mise en œuvre doit faire face à un comportement indéfini et, en fait, la mise en œuvre pourrait optimiser sortir un comportement indéfini et toujours être conformes à la norme. Pour être clair, la mise en œuvre définies comportement est un comportement qui n'est pas spécifié par la norme, mais la mise en œuvre du document. Un comportement indéfini est du code non portable ou erronées et dont le comportement est imprévisible et ne peut donc pas être invoqué.

Si l'on regarde le C99 projet de norme section 3.4.3 comportement indéfini qui vient sous les Termes, définitions et symboles de la section au paragraphe 1 il est dit(l'accent de la mine et à l'avenir):

problème, lors de l'utilisation d'un non-compatibles ou erronées programme de construction ou de données erronées, pour lequel la présente Norme Internationale n'impose pas d'exigences

et dans le paragraphe 2 , dit:

NOTE Possible un comportement indéfini plages d'ignorer la situation complètement avec des résultats imprévisibles, à se comporter lors de la traduction ou de l'exécution du programme dans documenté de façon caractéristique de l'environnement (avec ou sans émission d'un message de diagnostic), à la terminaison d'une traduction ou d'exécution (avec l'émission d'un message de diagnostic).

Modifier

En revanche, si vous souhaitez simplement une méthode définie dans la norme qui va provoquer une erreur de segmentation sur la plupart des Unix-like , puis raise( SIGSEGV ) devrait lui permettre d'atteindre cet objectif. Bien que strictement parlant SIGSEGV est définie comme suit:

SIGSEGV un accès non valide pour le stockage

et la section 7.14 de traitement de Signal , dit:

Une mise en œuvre n'a pas besoin de générer de l'un de ces signaux, sauf à la suite d'explicite les appels à la relance de la fonction. D'autres signaux et des pointeurs vers undeclarable fonctions, avec des macro-définitions début, respectivement, avec les lettres d'un SIG et une majuscule lettre ou avec SIG_ et une lettre majuscule,219) peut également être spécifié par le la mise en œuvre. L'ensemble des signaux, leur sémantique et leur gestion par défaut la mise en œuvre est définie; tous les signaux, les nombres doivent être positives.

34voto

Nikos C. Points 18676

La norme mentionne seulement un comportement indéfini. Il ne sait rien à propos de la mémoire de la segmentation. Notez également que le code qui génère l'erreur n'est pas la norme-conforme. Votre code ne peut se prévaloir d'un comportement indéfini et être conforme à la norme en même temps.

Néanmoins, le chemin le plus court pour produire une faute de segmentation sur des architectures qui ne génèrent de telles fautes serait:

int main()
{
    *(int*)0 = 0;
}

Pourquoi est-ce sûr de produire une erreur de segmentation? Parce que l'accès à la mémoire l'adresse 0 est toujours piégé par le système; il ne peut jamais être d'accès valide (au moins pas par le code en espace utilisateur.)

Notez bien sûr que non toutes les architectures de la même façon. Sur certains d'entre eux, le ci-dessus pourrait ne plantera pas à tous, mais plutôt de produire d'autres types d'erreurs. Ou la déclaration pourrait être parfaitement bien, même, et la mémoire est à la position 0 est accessible à l'amende juste. Qui est l'une des raisons pour lesquelles le standard n'a pas vraiment définir ce qui se passe.

14voto

Kerrek SB Points 194696

Un bon programme ne produit pas d'erreur de segmentation. Et vous ne pouvez pas décrire déterministe du comportement d'un programme incorrect.

Un "segmentation fault" est une chose qu'un PROCESSEUR x86. Vous obtenez en tentant de la mémoire de référence dans la mauvaise voie. Il peut également se référer à une situation où l'accès à la mémoire sont les causes d'un défaut de page (c'est à dire en essayant d'accéder à la mémoire qui n'est pas chargé dans la page tables) et le système d'exploitation décide que tu n'avais pas le droit de demander que la mémoire. Pour déclencher ces conditions, vous devez le programmer directement pour votre système d'exploitation et votre matériel. Il n'est rien spécifié par le langage C.

9voto

ouah Points 75311

Si nous supposons que nous ne sommes pas élever un signal appelant raise, faute de segmentation est susceptible de provenir d'un comportement indéfini. Un comportement non défini n'est pas défini et un compilateur est libre de refuser de traduire, donc pas de réponse définie l'échec est garanti sur toutes les implémentations. En outre, un programme qui invoque un comportement indéfini est un programme erroné.

Mais celui-ci est le plus court que je peux obtenir ce que l'erreur de segmentation sur mon système:

main(){main();}

(Je compile avec gcc et -std=c89 -O0).

Et par la manière, ce programme ne fait vraiment invoque pas défini bevahior?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X