2015-07-24 13 views
5

Questo codice fa un errore di segmentazione:Nessun errore di segmentazione con la forcella

int main(int argc, char *argv[]){ 
    int *n; 
    *n = atoi(argv[1]); 
    printf("n: %d \n", *n); 
    return 0; 
} 

mentre questo funziona:

int main(int argc, char *argv[]){ 
    int *n; 
    *n = atoi(argv[1]); 
    pid_t pid = fork(); 
    if (pid == 0) 
    return 0; 
    else 
    printf("n: %d \n", *n); 
    return 0; 
} 

Perché la seconda con la forcella funziona? So che dopo lo int *n, dovrei allocare lo spazio per unocon uno malloc(), ma l'utilizzo dello fork() sembra farlo automaticamente.

modifica: Ora capisco Comportamento non definito :) Ma ora sto chiedendo: qual è la causa in questo caso specifico?

+6

comportamento indefinito non è definito; tutto può succedere e il risultato è legittimo. Non invocare comportamenti non definiti. –

+0

"Qualcuno una volta mi ha detto che nel basket non puoi tenere la palla e scappare, ho preso un pallone da basket e l'ho provato e ha funzionato bene, ovviamente non ha capito il basket." - Roger Miller su comportamento non definito –

risposta

6

Non funziona. (O più precisamente, hai un comportamento indefinito)

1) Il fork nasconde semplicemente il segfault, perché non stai controllando il codice di uscita del processo figlio.

2) L'allocazione della memoria non è automatica - mai!

Stai semplicemente scrivendo in una posizione casuale e potresti essere solo "fortunato" che nella seconda versione la posizione casuale si trova all'interno dello spazio del processo.

+1

Oppure fa "lavoro" (con il mezzo di non andare in crash), ma dal momento che è UB, può fare qualsiasi cosa .. –

+0

funziona io: ./test 100 e ottengo n: 100 – joumvaer92

+4

@ joumvaer92 - che è solo "casuale" "fortuna - hai danneggiato qualcosa nello spazio del tuo processo - è solo" fortunato "che non causa un crash. – Soren

4

sia il vostro frammenti di codice invocano undefined behaviour, cortesia,

  1. utilizzando la memoria Non inizializzato e non valida *n
  2. (forse) usando Non inizializzato e invalida la memoria argv[1] (se argc non è >=2)

L'errore di segmentazione è uno dei molti effetti collaterali di UB. La custodia UB include anche lo che funziona perfettamente nello scenario.

Perché il secondo con la forcella funziona?

Non ha nulla a che fare con la presenza (o l'assenza) di fork() UB. TL; DR.

ma utilizzando la forcella() sembra farlo automaticamente.

Le immagini possono essere ingannevoli. Non mettere i tuoi soldi su UB.

3

Poiché n non è inizializzato e pertanto punta a un indirizzo di memoria sconosciuto, si sta invocando un comportamento non definito. Potrebbe andare in crash (come nel primo esempio) o potrebbe non esserlo (come nel secondo esempio).

In una situazione come questa, qualcosa di semplice come l'aggiunta di una variabile inutilizzata può causare un arresto anomalo del programma che non era prima o viceversa.

Assegna memoria per n e non si avrà questo problema.

Edit:

Il fatto che l'esecuzione di opere ./test 100 quando si esegue il secondo programma, non importa quante volte, è una questione di fortuna. Il fatto che tu abbia aggiunto una chiamata a fork (in questo caso) è accaduto per riorganizzare il modo in cui la memoria è strutturata in modo che funzioni. In seguito potresti decidere di effettuare una chiamata a printf per eseguire il debugging e all'improvviso riprenderà a bloccarsi.

L'aggiunta della chiamata fork non ha assegnato automaticamente spazio.

L'unico modo per impedire un incidente è allocare memoria per n, e per assicurare che argc è almeno 2 in modo che argv[1] punti da qualche parte significativa.

0

capita che non si vede il segfault come durante l'esecuzione di forchetta e restituisce 0, il codice non viene eseguito printf ("% d", *n)

Il fallo di segmentazione si verifica quando si tenta di accedere a una posizione di memoria che non è consentito, per cui la soluzione è assegnare una memoria ana tramite le funzioni malloc o calloc, altrimenti il ​​problema persiste. Prova questo:

n=malloc(sizeof(int)); 
*n=atoi(argv[1]); 

Saluti

+0

Non dovrebbe essere '* n = atoi (argv [1]);'? – dbush

+0

Il che significa che si desidera assegnare il valore di ritorno di 'atoi' a ciò che' n' punta a, cioè.'N' *. Altrimenti si sta sovrascrivendo il valore di ritorno di 'malloc'. – dbush

+0

@dbush Non capisco cosa intendi, grazie per la correzione – santiago92