2013-08-21 9 views
5

Sto scrivendo un programma in cui la maggior parte delle funzioni della libreria utilizzata restituisce -1 su errore e imposta errno. Il comportamento del programma è tale che esce se si verifica un errore. Per determinare esattamente punto di uscita e l'errore di fuori del programma (ad esempio utilizzando gdb), voglio usare il metodo seguente:E 'sicuro assumere errno essere sempre positivo?

err = func_1(..arglist_1..); 
if(err != 0) 
{ 
    perror("func(..arglist..)"); 
    return ((1u << 8) | errno); 
} 
//.. 
//.. some more funcs 
//.. 
err = func_n(..arglist_n..); 
if(err != 0) 
{ 
    perror("func(..arglist_n..)"); 
    return (((unsigned)n << 8) | errno); 
} 

Il problema qui è ipotesi sicure.

Realtà:errno è dichiarato come extern int errno; all'interno errno.h
Assunzione 1: Valore di errno è sempre inferiore a 255.
Ipotesi 2:errno è sempre positivo.

Sulla base di tutte le costanti di errore (EAGAIN, ecc.) Definite in errno.h, al momento queste ipotesi sono vere. Si può ritenere che ciò sia vero anche in futuro?

P.S .: Non voglio dipendere da perror() per determinare il punto di uscita.

+0

Dubito che entrambe le ipotesi siano sicure. Per il secondo, consideri '0' positivo? – jxh

+0

No '0' è escluso poiché [questo collegamento qui] (http://pubs.opengroup.org/onlinepubs/009695399/functions/errno.html) dice:" Non verrà impostata alcuna funzione in questo volume di IEEE Std 1003.1-2001 errno a 0! –

+2

Proprio perché nessuna funzione nella libreria standard la imposta su '0' non significa che qualcun altro non lo imposta a' 0'. Per alcune funzioni di libreria standard, l'unico modo per determinare se la chiamata non è riuscita è innanzitutto impostare 'errno' su' 0' e poi vedere cosa fa la funzione. – jxh

risposta

12

Lo stato di uscita del programma è limitato a 0,25, quindi se tali istruzioni di ritorno provengono dal programma main(), i bit di ordine superiore sono irrilevanti.

Lo standard C (ISO/IEC 9899: 2011 §7.5 errori <errno.h>) dice:

errno
che si espande ad un lvalue modificabile 201) che ha tipo int e filo memoria locale durata , il cui valore è impostato su un numero di errore positivo da diverse funzioni della libreria.

201) La macro errno non deve essere l'identificatore di un oggetto. Potrebbe espandersi a un valore lvalue risultante da una chiamata di funzione (ad esempio, *errno()).

Lo standard C si aspetta che gli errori siano positivi. POSIX (IEEE Std 1003.1, edizione 2013) stabilisce per <errno.h>:

L'intestazione <errno.h> definisce le seguenti macro che ampliano a intero espressioni costanti di tipo int, valori positivi distinti (tranne per quanto qui di seguito), e che deve essere adatto per l'uso in #if direttive al preprocessore: ...

Quindi, si può ragionevolmente supporre con sicurezza che (generato dal sistema) numeri degli errori sono positivi, ma il codice può impostare errno negativo (o zero). Al momento, nessun sistema POSIX genera numeri di errore superiori a qualche parte inferiore a 200, quindi supponendo che saranno limitati a 255 è sicuro nel breve termine, ma probabilmente non a lungo termine. Non c'è motivo per cui dovrebbero essere così limitati.

La "realtà" rivendicata si applica solo ai programmi senza thread. Se si sta compilando per il supporto con thread, quindi non è semplicemente dichiarato come extern int errno; e in nessuna circostanza si dovrebbe tentare di dichiarare errno per sé. Il solo modo sicuro per dichiararlo tramite l'intestazione <errno.h>.

+0

Ok, ho avuto la mia risposta, grazie Jonathan Leffler. Prima di tutto, ha ragione, intendevo farlo in main(). Successivamente, il mio errore mi sono dimenticato dei programmi multithread. Inoltre ho usato [copia più vecchia dello standard] (http://pubs.opengroup.org/onlinepubs/009695399/functions/errno.html) come riferimento, non è stato detto che sarà sempre positivo. –

+1

C89 non ha stabilito che i numeri di errore fossero positivi (solo non zero); C99 ha stabilito che i numeri di errore erano positivi. È interessante notare che POSIX 1997 ha dichiarato che "L'intestazione' 'fornisce una dichiarazione per errno e fornisce valori diversi da zero per le seguenti costanti simboliche." che è coerente con lo standard C89 (C90) corrente. –

+0

@nishant: interessante: sei collegato alla pagina POSIX 2004 per 'errno', che non menziona il 'positivo' (e nemmeno la pagina POSIX 2013 per [' errno'] (http: //pubs.opengroup. org/onlinepubs/9699919799/functions/errno.html)), mentre sono collegato alla pagina POSIX (2013) per '', che lo menziona (come fa la pagina POSIX 2004 per l'intestazione). Immagino di aver avuto la fortuna di scegliere il posto giusto dove guardare; Non ero a conoscenza dell'asimmetria. –

Problemi correlati