Quand argv peut-il avoir la valeur null?

Ce que j’ai compris au sujet du passage d’arguments à main () à partir de la ligne de commande, c’est que argc a une valeur minimale de 1 et qu’argv [0] aura toujours le nom du programme avec son chemin.

Si des arguments sont fournis sur la ligne de commande, argc aura une valeur supérieure à un et argv 1 à argv [argc-1] aura ces arguments.

Maintenant, un paragraphe à ce lien dit que

argv [0] sera une chaîne contenant le nom du programme ou une chaîne nulle si elle n’est pas disponible.

Maintenant, comment et quand argv [0] peut-il avoir une chaîne nulle? Je veux dire que le nom du programme avec son chemin sera toujours disponible alors quand peut-il être nul?

Writer dit que “si ce n’est pas disponible” mais quand et comment il est possible que le nom du programme ne soit pas disponible?

Avec la classe d’appels exec , vous spécifiez le nom du programme et l’ exécutable du programme séparément afin de pouvoir le définir sur NULL.

Mais cette citation est en réalité issue de la norme ISO (peut-être paraphrasée) et cette norme couvre une gamme extrêmement étendue d’environnements d’exécution, du plus petit micro-contrôleur au dernier ordinateur central de classe entreprise z10.

Un grand nombre de ces systèmes intégrés se trouveraient dans la situation où un nom d’exécutable n’aurait aucun sens.

Depuis le dernier brouillon c1x:

La valeur de argc doit être non négative.

La valeur argv[argc] doit être un pointeur nul.

Si la valeur de argc est supérieure à zéro, les membres du tableau argv[0] à argv[argc-1] inclus doivent contenir des pointeurs sur des chaînes, auxquelles l’environnement hôte donne des valeurs définies par l’implémentation avant le démarrage du programme.

Cela signifie que, si argc vaut zéro (et ce peut être le cas), argv [0] est nul.

Toutefois, même lorsque argc n’est pas égal à 0, vous ne pouvez pas obtenir le nom du programme, car la norme indique également:

Si la valeur de argc est supérieure à zéro, la chaîne pointée par argv[0] représente le nom du programme. argv[0][0] doit être un caractère nul si le nom du programme n’est pas disponible dans l’environnement hôte. Si la valeur de argc est supérieure à 1, les chaînes argv[1] par argv[1] à argv[argc-1] représentent les parameters du programme.

Ainsi, la norme n’exige pas qu’un nom de programme soit fourni. J’ai vu des programmes utiliser une large sélection d’options pour cette valeur:

  • aucune valeur du tout (pour une sécurité supposée).
  • un mensonge flagrant (comme sleep pour un morceau de code malveillant).
  • le nom du programme actuel (tel que sleep ).
  • légèrement modifié (tel que -ksh pour le shell de connexion).
  • un nom descriptif (par exemple, progname - a program for something ).

Selon cette liste de diffusion , argv[0] peut être nul si argc == 0 . Mais ils n’expliquent pas quand argc pourrait être égal à zéro. J’imagine que argc serait nul dans les cas où un exécutable n’était pas lancé “normalement” (c’est-à-dire via une ligne de commande, popen , etc.) – et en effet, comme @paxdiablo l’a mentionné, vous pouvez définir manuellement argv avec la famille exec de fonctions , donc argc pourrait être nul en fonction de ces arguments.

Mais, dans leur section Justification :

Les premières propositions exigeaient que la valeur de argc transmise à main() soit “un ou plus”. Ceci était motivé par les mêmes exigences dans les projets de norme ISO C. En fait, les implémentations historiques ont dépassé la valeur zéro lorsqu’aucun argument n’a été fourni à l’appelant des fonctions exec. Cette exigence a été supprimée de la norme ISO C et par la suite de ce volume de la norme IEEE Standard 1003.1-2001. Le libellé, en particulier l’utilisation du mot devrait obliger une application POSIX à conformité ssortingcte à transmettre au moins un argument à la fonction exec, garantissant ainsi que argc soit argc ou supérieur à un lorsqu’il est appelé par une telle application. En fait, c’est une bonne pratique, car de nombreuses applications existantes font référence à argv[0] sans d’abord vérifier la valeur de argc .

Voilà donc tout: les applications POSIX ssortingctement conformes doivent avoir une valeur supérieure à zéro pour argc , mais cela n’est nullement garanti.

Il y a un peu plus d’informations sur la norme concernant argc et argv dans la section Démarrage du programme .

Il est possible d’imaginer des plates-formes où les programmes n’ont pas de nom – peut-être que le code est simplement chargé au démarrage. Sur ceux-ci, argv [0] pourrait devenir NULL. La norme C autorise certainement une valeur argc de zéro et indique que argv [argc] doit être NULL.

Exemple POSIX exécutable

ac

 #define _XOPEN_SOURCE 700 #include  int main(void) { char *argv[] = {NULL}; char *envp[] = {NULL}; execve("b.out", argv, envp); } 

bc

 #include  int main(int argc, char **argv) { if (argc == 0 && argv[0] == NULL) puts("yup"); } 

Ensuite:

 gcc ac -o a.out gcc bc -o b.out ./a.out 

Donne:

 yup 

Testé sous Ubuntu 16.10.

Tester le programme existant avec une liste d’arguments vide

Voici un wrapper qui prend un chemin comme argument et qui l’exécute comme une commande sans argument:

 #include  #include  int main(int argc, char**argv) { char *empty[] = {NULL}; execve(argv[1], empty, empty); perror("empty-args: execve failed"); // Bad Address (EFAULT) if our argv[1] == NULL return 1; } 

usage:

 ./empty-args ./arg-count