Accéder aux arguments de ligne de commande sans utiliser char ** argv dans main

Existe-t-il un moyen d’accéder aux arguments de ligne de commande sans utiliser l’argument de main? Je dois y accéder via une autre fonction et je préférerais ne pas la transmettre.

J’ai besoin d’une solution qui ne fonctionne nécessairement que sur Mac OS et Linux avec GCC.

Je ne pense pas que vous devriez le faire car le runtime C préparera les arguments et les transmettra au principal via int argc, char **argv , ne tentez pas de manipuler le comportement en le piratant car il serait en grande partie inportable ou éventuellement comportement indéfini !! Tenez-vous-en aux règles et vous aurez la portabilité… pas d’autre moyen de le faire que de le violer…

Je ne sais pas comment le faire sur MacOS, mais je soupçonne que le truc que je vais décrire ici peut être transféré sur MacOS avec un peu de lecture croisée.

Sous Linux, vous pouvez utiliser la section dite “.init_array” du fichier binary ELF pour enregistrer une fonction qui est appelée lors de l’initialisation du programme (avant l’appel de main ()). Cette fonction a la même signature que la fonction main () normale, sauf qu’elle renvoie “void”. Ainsi, vous pouvez utiliser cette fonction pour mémoriser ou traiter argc, argv [] et evp [].

Voici du code que vous pouvez utiliser:

 static void my_cool_main(int argc, char* argv[], char* envp[]) { // your code goes here } __atsortingbute__((section(".init_array"))) void (* p_my_cool_main)(int,char*[],char*[]) = &my_cool_main; 

PS: Ce code peut également être placé dans une bibliothèque, il devrait donc convenir à votre cas. Cela fonctionne même lorsque votre programme est exécuté avec valgrind – valgrind ne lance pas un nouveau processus et le résultat est / proc / self / cmdline montrant la ligne de commande d’origine valgrind.

PPS: N’oubliez pas qu’au cours de l’exécution très précoce du programme, de nombreux sous-systèmes ne sont pas encore complètement initialisés – j’ai essayé les routines d’E / S de libc, elles semblent fonctionner, mais ne vous en fiez pas – même les variables gloval peuvent ne pas encore être construites etc…

Vous pouvez les copier dans des variables globales si vous le souhaitez.

Vous pouvez. La plupart des plateformes fournissent des variables globales __argc et __argv. Mais encore une fois, je soutiens le commentaire de zneak.

PS Utilisez boost :: program_options pour les parsingr. S’il vous plait, ne le faites pas autrement en C ++.

Sous Linux, vous pouvez ouvrir /proc/self/cmdline (en supposant que /proc est présent) et parsingr manuellement (cela n’est requirejs que si vous avez besoin de argc / argv avant main() – par exemple dans un constructeur global – sinon il vaut mieux passez-les via vars global).

Plus de solutions sont disponibles ici: http://blog.linuxgamepublishing.com/2009/10/12/argv-and-argc-and-just-how-to-get-them-th/

Oui, c’est grossier et inutilisable, mais si vous résolvez des problèmes pratiques, vous ne vous en souciez peut-être pas.

Y a-t-il une raison pour laquelle passer un pointeur sur l’espace déjà consommé est si mauvais? En éliminant l’argument de la fonction en question, vous ne gagnerez pas vraiment d’argent et vous pourriez déclencher une exposition intéressante de feux d’artifice. En contournant la stack d’appels de main () avec le hackery créatif, on aboutit généralement à un comportement non défini ou à un comportement spécifique du compilateur. Les deux sont mauvais pour la fonctionnalité et la portabilité, respectivement.

N’oubliez pas que les arguments en question sont des pointeurs vers des arguments, ils vont occuper de l’espace, peu importe ce que vous faites. La commodité de leur index est aussi bon marché que sizeof (int), je ne vois aucune raison de ne pas l’utiliser.

On dirait que vous optimisez de manière plutôt agressive et prématurée, ou que vous devez append des fonctionnalités au code que vous ne voulez vraiment pas gâcher. Dans les deux cas, faire les choses de manière conventionnelle fera gagner du temps et des problèmes.