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 tableauargv[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 parargv[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 deargc
est supérieure à 1, les chaînesargv[1]
parargv[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:
sleep
pour un morceau de code malveillant). sleep
). -ksh
pour le shell de connexion). 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 queargc
soitargc
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 deargc
.
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