2013-08-20 11 views
7

seguito riporta il codice C che è destinato a mandare in crash:in perl, come possiamo rilevare un errore di segmentazione in un comando esterno

#include<stdio.h> 
#include<stdlib.h> 

int main() { 
    char *p = NULL; 
    printf("Value at P: %c\n", *p); 
    return 0; 
} 

Quando compilo ed eseguirlo (macchina RH4 con gcc 4.5.2), dà prevedibilmente un errore di segmentazione:

% ./a.out 
Segmentation fault 

% echo $status 
139 

Se l'eseguo con Perl v5.8.5, questo accade:

% perl -e 'system("./a.out") and die "Status: $?"' 
Status: 11 at -e line 1. 

Th e perlvar documentazione per $? dice che

Così, il valore di uscita del sottoprocesso è davvero ($?>> 8), e $? & 127 dà quale segnale, se del caso, il processo è morto, e $? & 128 rapporti se ci fosse un core dump.

11 >> 8 è 0, e 11 & 127 è 11.

Perché i diversi stati di uscita? Se non possiamo dipendere dallo stato di uscita, quale dovrebbe essere il modo di rilevare l'errore di segmentazione in un comando esterno?

+0

Come viene impostato '$ stato'? – Zaid

+4

Sembra che tu stia effettivamente ricevendo il segnale dal quale il processo è morto: 11 è un errore di segmentazione e '139 & 127 = 11' –

+0

L'ho appena provato con Cygwin (perl v 5.14.2) e mi ha dato:' Stato : 139 at -e line 1.' –

risposta

13

Leggendo la documentazione per system potrebbe rispondere alla tua domanda:

system('a.out'); 

if ($? == -1) { 
    print "failed to execute: $!\n"; 
} 
elsif ($? & 127) { 
    printf "child died with signal %d, %s coredump\n", 
     ($? & 127), ($? & 128) ? 'with' : 'without'; 
} 
else { 
    printf "child exited with value %d\n", $? >> 8; 
} 

uscita:

child died with signal 11, without coredump 

Il guscio solo codifica il segnale nello stato in un modo diverso: 139-128 = 11. Ad esempio,

Il valore di ritorno di un comando semplice è la sua exi t stato, o 128 + n se il comando è terminato dal segnale n.

+0

davvero informativo.quindi idealmente, tutti i valori dei segnali dovrebbero essere superiori a 128 ... – Unos

+1

@Unos, i numeri di segnale iniziano da 1 e possono salire fino a 127. I codici di uscita superiori a 128 dalla shell sono ambigui poiché si schiaccia "uccisi dal segnale" e " usciti con errore "numeri insieme. per esempio. è '139' un kill di SEGFAULT o' exit (139) '? Non posso dire dalla shell, ma posso dirlo da Perl. – ikegami

+0

ok, quindi se ho capito bene, shell vede un segnale per seg-fault, '00001011', e imposta il bit più alto, quindi lo stato diventa' 10001011', o 139. Perl lo decodifica correttamente e imposta '$?' Su 11. – Unos

3

Il sistema operativo vede sempre la stessa cosa ... cosa viene restituito dalla famiglia di funzioni wait (2). sistema (3), et. tutto, chiama wait (2). Come si pecola te è ciò che sta causando le differenze. La shell e i programmi fanno cose diverse e segnalano diversi modi. Dovendo spostare a destra 8 per ottenere lo stato di uscita più comune sarebbe molto fastidioso nei programmi di shell e confondere gli utenti meno esperti di tecnologia.

Mentre i primi sistemi UNIX che ho usato (Unix originale) hanno avuto gli stessi ritorni mi sono sempre chiesto se le versioni pre-release fossero diverse e restituire il segnale e core/dump fossero un'aggiunta successiva.

La mia segnalazione preferita di stato di uscita tende ad avere il computer diviso i miei bit per me.

 my $x = $?; #save status 
    print("Exit status: %d.%d%s\n", 
       $x>>8, $x&127, ($x&128)?"*":"");
Problemi correlati