Question

Je test du code qui est conçu pour détecter le moment où un processus enfant a crashait. Imaginez ma surprise lorsque ce code ne fonctionne pas toujours segfault:

#include <stdio.h>

int main() {
  char *p = (char *)(unsigned long)0;
  putchar(*p);
  return 0;
}

Je suis en cours d'exécution sous un noyau Debian Linux 2.6.26; ma coquille est le AT & T ksh93 du paquet ksh Debian, la version M 93s + 2008-01-31. Parfois, ce programme, mais sinon il segmentation fault se termine simplement en silence avec un statut de sortie, mais aucun message non nul. Mon programme de signaux de détection indique ce qui suit:

segfault terminated by signal 11: Segmentation fault
segfault terminated by signal 53: Real-time signal 19
segfault terminated by signal 11: Segmentation fault
segfault terminated by signal 53: Real-time signal 19
segfault terminated by signal 53: Real-time signal 19
segfault terminated by signal 53: Real-time signal 19
segfault terminated by signal 53: Real-time signal 19

Fonctionnant sous ksh pur montre que le segfault est aussi rare:

Running... 
Running... 
Running... 
Running... 
Running... 
Running... Memory fault
Running... 

Il est intéressant, bash détecte correctement le segfault chaque fois .

J'ai deux questions:

  1. Quelqu'un peut-il expliquer ce comportement?

  2. Quelqu'un peut-il proposer un programme simple C qui segfault de manière fiable à chaque exécution? J'ai aussi triedkill(getpid(), SIGSEGV), mais j'obtenir des résultats similaires.


EDIT: jbcreix a la réponse : mon détecteur de segfault a été brisé. Je suis dupe parce que ksh a le même problème. J'ai essayé avec bash et bash obtient à chaque fois.

Mon erreur était que je passais WNOHANG à waitpid(), où je viens de passer à zéro. Je ne sais pas ce que j'aurais pensé! On se demande ce qui est de la question avec ksh, mais c'est une autre question.

Était-ce utile?

La solution

Ecrire à NULL sera fiable ou segfault erreur de bus.

Parfois, un OS mapper une page en lecture seule à l'adresse zéro. Ainsi, vous pouvez parfois lire NULL.

Bien que C définit l'adresse NULL comme spéciale, la « mise en œuvre » de ce statut particulier est en fait gérée par le sous-système de mémoire virtuelle du système d'exploitation (VM).

VIN et dosemu doivent corréler une page à NULL pour la compatibilité avec Windows. Voir mmap_min_addr dans le noyau Linux pour reconstruire un noyau qui ne peut pas le faire.

mmap_min_addr est actuellement un sujet brûlant en raison d'une associée et une flamme exploit du public envers Linus (de la renommée Linux, évidemment) de Theo de Raadt, de l'effort OpenBSD.

Si vous êtes prêt à coder l'enfant de cette façon, vous pouvez toujours appeler: raise(SIGSEGV);

En outre, vous pouvez obtenir un pointeur à segfault garanti à partir de: int *ptr_segv = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS, -1, 0);

PROT_NONE est la clé de réserver la mémoire qui ne peut pas être accessible. 32 bits Intel Linux, PAGE_SIZE est 4096.

Autres conseils

Je ne sais pas pourquoi il n'a pas un comportement cohérent. Je pense que ce n'est pas aussi tatillon avec la lecture. Ou quelque chose comme ça, si je serait probablement tout à fait tort.

Essayez d'écrire à NULL. Cela semble être cohérent pour moi. Je ne sais pas pourquoi vous voulez utiliser ce bien. :)

int main()
{
    *(int *)0 = 0xFFFFFFFF;
    return -1;
}

La réponse à la question numéro deux de Wikipedia :

 int main(void)
 {
     char *s = "hello world";
     *s = 'H';
 }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top