Domanda

Nell'ambiente C / Unix in cui lavoro, vedo alcuni sviluppatori che usano __progname invece di argv [0] per i messaggi di utilizzo. C'è qualche vantaggio in questo? Qual è la differenza tra __progname e argv [0] . È portatile?

È stato utile?

Soluzione

__progname non è standard e quindi non portatile, preferisce argv [0] . Suppongo che __progname potrebbe cercare una risorsa stringa per ottenere il nome che non dipende dal nome del file in cui è stato eseguito. Ma argv [0] ti darà il nome che in realtà ha eseguito come se lo trovassi più utile.

Altri suggerimenti

L'uso di __progname consente di modificare il contenuto dell'array argv [] mantenendo comunque il nome del programma. Alcuni degli strumenti comuni come getopt () modificano argv [] mentre elaborano gli argomenti.

Per la portabilità, puoi strcopy argv [0] nel tuo buffer progname all'avvio del programma.

Esiste anche un'estensione GNU per questo, in modo che si possa accedere al nome di chiamata del programma dall'esterno di main () senza salvarlo manualmente. Uno potrebbe essere meglio farlo manualmente, tuttavia; rendendolo così portatile anziché affidarsi all'estensione GNU. Tuttavia, qui fornisco un estratto dalla documentazione disponibile.

Da the manuale della libreria C GNU on-line (accessibile oggi):

" Molti programmi che non leggono l'input dal terminale sono progettati per uscire se una chiamata di sistema fallisce. Per convenzione, il messaggio di errore di un tale programma dovrebbe iniziare con il nome del programma, senza directory. Puoi trovare quel nome nella variabile program_invocation_short_name ; il nome file completo è memorizzato nella variabile nome_programma_vocazione .

  • Variabile: char * nome_invocazione_programma Il valore di questa variabile è il nome utilizzato per richiamare il programma in esecuzione nel processo corrente. È lo stesso di argv [0] . Si noti che questo non è necessariamente un nome file utile; spesso non contiene nomi di directory.

  • Variabile: char * program_invocation_short_name Il valore di questa variabile è il nome utilizzato per richiamare il programma in esecuzione nel processo corrente, con i nomi di directory rimossi. (Vale a dire, è lo stesso di nome_programma_vocazione meno tutto fino all'ultima barra, se presente.

Il codice di inizializzazione della libreria imposta entrambe queste variabili prima di chiamare main.

Nota sulla portabilità: queste due variabili sono estensioni GNU. Se si desidera che il programma funzioni con librerie non GNU, è necessario salvare il valore di argv [0] in main, quindi rimuovere personalmente i nomi delle directory. Abbiamo aggiunto queste estensioni per rendere possibile la scrittura di subroutine autonome per la segnalazione degli errori che non richiedono alcuna cooperazione esplicita dalla rete principale. & Quot;

Vedo almeno due potenziali problemi con argv [0].

In primo luogo, argv [0] o argv stesso possono essere NULL se il chiamante execve () era abbastanza malvagio o poco attento. Chiamare execve (" foobar " ;, NULL, NULL) di solito è un modo semplice e divertente per dimostrare a un programmatore troppo fiducioso che il suo codice non è a prova di sig11.

Va ??anche notato che argv non sarà definito al di fuori di main () mentre __progname è generalmente definito come una variabile globale che puoi usare dalla tua funzione use () o anche prima che venga chiamato main () (come non standard Costruttori GCC).

È un BSDismo e sicuramente non portatile.

__progname è solo argv [0], e esempi in altre risposte qui mostrano i punti deboli del suo utilizzo. Sebbene non sia portatile, sto usando readlink su / proc / self / exe (Linux, Android) e sto leggendo il contenuto di / proc / self / exefile (QNX).

Se il programma è stato eseguito utilizzando, ad esempio, un collegamento simbolico, argv [0] conterrà il nome di quel collegamento.

Suppongo che __progname conterrà il nome del file di programma effettivo.

In ogni caso, argv [0] è definito dallo standard C. __progname non lo è.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top