Domanda

Sto testando il codice che è stato progettato per rilevare quando un processo figlio ha segfaulted.Immaginate la mia sorpresa quando questo codice non sempre segmentation fault:

#include <stdio.h>

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

Io sono in esecuzione su un Debian Linux kernel 2.6.26;il mio guscio è AT&T ksh93 da Debian ksh pacchetto, la Versione M 93s+ 2008-01-31.A volte questo programma segfault ma per il resto è semplicemente termina in silenzio con uno stato di uscita diverso da zero, ma nessun messaggio.Il mio segnale di rilevamento programma segnala il seguente:

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

L'esecuzione in puro ksh mostra che il segmentation fault è anche raro:

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

È interessante notare che, bash rileva correttamente il segfault ogni volta.

Ho due domande:

  1. Qualcuno può spiegare questo comportamento?

  2. Qualcuno può suggerire un semplice programma in C che segfault affidabile su ogni esecuzione?Ho anche provatokill(getpid(), SIGSEGV), ma io ottenere risultati simili.


EDIT: jbcreix ha la risposta:il mio segmentation fault detector era rotto.Sono stato ingannato, perché ksh ha lo stesso problema.Ho provato con bash e bash si è giusto ogni volta.

Il mio errore era che stavo passando WNOHANG per waitpid(), dove avrei dovuto passare zero.Non so cosa avrei potuto pensare!Uno si chiede che cosa è la questione con ksh, ma che è una questione a parte.

È stato utile?

Soluzione

La scrittura per NULL sarà affidabile segmentation fault o errore di bus.

A volte un OS mappa una pagina di sola lettura a zero indirizzo.Così, a volte si può leggere NULL.

Anche se C definisce il NULL indirizzo di speciale, la 'realizzazione' di quello speciale stato è in realtà gestita dal Sistema Operativo Memoria Virtuale (VM) sottosistema.

VINO e dosemu bisogno di una mappa di una pagina NULL per la compatibilità con Windows.Vedere mmap_min_addr nel kernel Linux per ricompilare un kernel che non può fare questo.

mmap_min_addr è attualmente un tema caldo grazie a una valorizzazione e di un pubblico di fiamma verso Linus (di Linux fama, ovviamente) da Theo de Raadt, di OpenBSD sforzo.

Se siete disposti a codice il bambino in questo modo, si può sempre chiamare: raise(SIGSEGV);

Inoltre, è possibile ottenere un garantite-di-segfault puntatore: int *ptr_segv = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS, -1, 0);

Dove PROT_NONE è la chiave di riserva di memoria, che non può essere letta.Per la versione a 32 bit di Intel Linux, PAGE_SIZE è di 4096.

Altri suggerimenti

Io non sono sicuro perché non hanno un comportamento coerente.Mi piacerebbe pensare che non è così esigente a livello con la lettura.O qualcosa di simile, anche se probabilmente sarei totalmente sbagliato.

Prova a scrivere a NULL.Questa sembra essere una costante per me.Non ho idea del perché si desidera utilizzare questo però.:)

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

La risposta alla domanda numero due da Wikipedia :

 int main(void)
 {
     char *s = "hello world";
     *s = 'H';
 }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top