Domanda

Ho trovato due modi per passare argomenti della riga di comando in una matrice di caratteri:

int main (int argc, char **argv)
{
  const char *s1 = argv[0];
  char s2[256];
  strcpy(s2, argv[0]);

  printf("s1: %s\ns2: %s\n\n", s1, s2);
}

Compilato con il compilatore xlc IBM su un sistema AIX Returns

  &

[MyPrompt] gt; ./a.out

     

s1: ./a.out

     

s2: ./a.out

Quale implementazione (s1 o s2) è corretta? s1 è carino perché argv [0] può essere di qualsiasi lunghezza. s2 richiede che la lunghezza di argv [0] < 256 caratteri.

Non capisco come / perché s1 dovrebbe funzionare. penso il lato destro di s1 dovrebbe essere richiesto in fase di compilazione, ma penso sia generato in fase di esecuzione.

È stato utile?

Soluzione

Il motivo per cui s1 funziona è perché il tipo di argv [0] è un puntatore. Stai semplicemente assegnando l'indirizzo (non il valore reale), che è sicuro. Non stai eseguendo alcun tipo di allocazione o cast.

Preferisco in genere la prima opzione poiché dovresti leggere solo dalle variabili dell'argomento.

Altri suggerimenti

Se non vuoi cambiare la stringa, allora s1 funzionerà.

Se vuoi cambiare la stringa, puoi crearne una copia. Dovresti usare il più sicuro strnlen () e strncpy () se il tuo sistema lo supporta.

  

Penso che il lato destro di s1   dovrebbe essere richiesto al momento della compilazione,   ma penso che sia generato a   run-time.

No, è richiesto ogni volta che si incontra la dichiarazione. Ad esempio:

void f() {
   int x = 1;
   ...
}

L'intero x verrà inizializzato su 1 ogni volta che viene chiamata la funzione, non in fase di compilazione.

s2 ha la deliziosa proprietà di essere sensibile a un sovraccarico del buffer.

Ho visto persone cambiare il valore di argv [0]. In alcuni casi, (su alcuni sistemi operativi) la modifica di argv [0] farà apparire il programma in ps come qualunque cosa tu abbia cambiato.

Se vuoi solo fare riferimento all'argomento senza apportare modifiche, s1 è corretto.

Se devi modificare l'argomento in qualche modo, devi crearne una copia come nell'esempio s2 , ma nell'esempio s2 devi controllare esplicitamente di vedere se la lunghezza è più lunga del buffer in cui lo si sta copiando. Ad esempio, se stai prendendo un argomento come nomefile.jpg come input e salvando nomefile.gif come output, allora devi fare una copia di tale argomento poiché cambierai l'estensione da .jpg a .gif

Vorrei andare con s1, specialmente per argv [n] dove n > 0. Cose come s2 ti aprono per i classici attacchi di overflow del buffer. Fondamentalmente, un utente può formattare un argomento di lunghezza superiore a 256 caratteri e sovrascrivere le informazioni nello stack in modo da poter eseguire qualsiasi codice desiderato.

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