Is “argv[0] = name-of-executable” een geaccepteerde standaard of gewoon een algemene conventie?

Als een argument wordt doorgegeven aan main()in een C- of C++-toepassing, zal argv[0]dan altijd de naam zijn van het uitvoerbare bestand? Of is dit gewoon een algemene conventie en is het niet gegarandeerd dat het 100% van de tijd waar is?


Antwoord 1, autoriteit 100%

Gissen (zelfs goed giswerk) is leuk, maar je moet echt naar de standaarddocumenten gaan om zeker te zijn. ISO C11 stelt bijvoorbeeld (mijn nadruk):

Als de waarde van argcgroter is dan nul, staat de tekenreeks waarnaar wordt verwezen door argv[0]voorde programmanaam; argv[0][0]is het null-teken als de programmanaam niet beschikbaar is in de hostomgeving.

Dus nee, het is alleen de programmanaam als die naam beschikbaar is.En het ‘vertegenwoordigt’de programmanaam, niet per se isde programmanaam. In het gedeelte daarvoor staat:

Als de waarde van argcgroter is dan nul, zullen de arrayleden argv[0]tot en met argv[argc-1]inclusief bevatten verwijzingen naar tekenreeksen, die door de hostomgeving vóór het opstarten van het programma door de implementatie gedefinieerde waarden krijgen.

Dit is ongewijzigd ten opzichte van C99, de vorige standaard, en betekent dat zelfs de waardenniet door de standaard worden gedicteerd – het is volledig aan de implementatie.

Dit betekent dat de programmanaam leeg kan zijn als de hostomgeving deze nietlevert, en al het andere als de hostomgeving deze welverschaft, op voorwaarde dat ” iets anders” vertegenwoordigt op de een of andere manier de programmanaam. Op mijn meer sadistische momenten zou ik overwegen om het in het Swahili te vertalen, het door een substitutiecijfer te laten lopen en het vervolgens in omgekeerde bytevolgorde op te slaan :-).

Implementatiegedefinieerde heeft echtereen specifieke betekenis in de ISO-normen – de implementatie moet documenteren hoe het werkt. Dus zelfs UNIX, dat alles wat het wil in argv[0]kan stoppen met de exec-familie van aanroepen, moet (en doet) het documenteren.


Antwoord 2, autoriteit 41%

Onder systemen van het type *nixmet exec*()-aanroepen, zal argv[0]zijn wat de beller in de argv0-plek in de exec*()-aanroep.

De shell gebruikt de conventie dat dit de programmanaam is, en de meeste andere programma’s volgen dezelfde conventie, dus argv[0]meestal de programmanaam.

Maar een malafide Unix-programma kan exec()aanroepen en argv[0]alles maken wat het wil, dus wat de C-standaard ook zegt, je kunt het niet reken hier 100% van de tijd op.


Antwoord 3, autoriteit 7%

Volgens de C++-standaard, sectie 3.6.1:

argv[0] is de aanwijzer naar de
beginteken van een NTMBS die
staat voor de naam die wordt gebruikt om de . aan te roepen
programma of “”

Dus nee, het wordt niet gegarandeerd, althans niet door de Standaard.


Antwoord 4, autoriteit 5%

ISO-IEC 9899 stelt:

5.1.2.2.1 Opstarten van programma

Als de waarde van argcgroter is dan nul, wordt de tekenreeks waarnaar wordt verwezen door argv[0]vertegenwoordigt de programmanaam; argv[0][0]is het null-teken als de programmanaam niet beschikbaar is in de hostomgeving. Als de waarde van argcgroter is dan één, worden de tekenreeksen waarnaar wordt verwezen door argv[1]tot en met argv[argc-1]vertegenwoordigen de programmaparameters.

Ik heb ook gebruikt:

#if defined(_WIN32)
  static size_t getExecutablePathName(char* pathName, size_t pathNameCapacity)
  {
    return GetModuleFileNameA(NULL, pathName, (DWORD)pathNameCapacity);
  }
#elif defined(__linux__) /* elif of: #if defined(_WIN32) */
  #include <unistd.h>
  static size_t getExecutablePathName(char* pathName, size_t pathNameCapacity)
  {
    size_t pathNameSize = readlink("/proc/self/exe", pathName, pathNameCapacity - 1);
    pathName[pathNameSize] = '\0';
    return pathNameSize;
  }
#elif defined(__APPLE__) /* elif of: #elif defined(__linux__) */
  #include <mach-o/dyld.h>
  static size_t getExecutablePathName(char* pathName, size_t pathNameCapacity)
  {
    uint32_t pathNameSize = 0;
    _NSGetExecutablePath(NULL, &pathNameSize);
    if (pathNameSize > pathNameCapacity)
      pathNameSize = pathNameCapacity;
    if (!_NSGetExecutablePath(pathName, &pathNameSize))
    {
      char real[PATH_MAX];
      if (realpath(pathName, real) != NULL)
      {
        pathNameSize = strlen(real);
        strncpy(pathName, real, pathNameSize);
      }
      return pathNameSize;
    }
    return 0;
  }
#else /* else of: #elif defined(__APPLE__) */
  #error provide your own implementation
#endif /* end of: #if defined(_WIN32) */

En dan hoeft u gewoon de tekenreeks te ontleden om de uitvoerbare naam uit het pad te halen.


Antwoord 5, Autoriteit 4%

toepassingen van het hebben van argv[0] !=uitvoerbare naam

  • Veel schelpen bepalen of ze een login-shell zijn door argv[0][0] == '-'te controleren. Aanmeldingsschelpen hebben verschillende eigenschappen, met name dat ze een aantal standaardbestanden vinden, zoals /etc/profile.

    Het is meestal de init zelf of gettydie de toonaangevende -, zie ook: HTTPS://unix.stackExchange.com/Questions/299408/HOW- To-login-automatisch-zonder-typ-the-root-gebruikersnaam-of-wachtwoord-in-build / 300152 # 300152

  • Multi-call binaries, misschien wel met name busybox . Deze symlink meerdere namen b.v. /bin/shEN /bin/lsNAAR EEN ENKELE EXEBLUTE /bin/busybox, die erkent welk gereedschap u wilt gebruiken van argv[0].

    Dit maakt het mogelijk om een ​​enkel klein statiek gekoppeld uitvoerbaar bestand te hebben dat meerdere hulpmiddelen vertegenwoordigt en in principe werkt op een Linux-omgeving.

Zie ook: HTTPS: //unix.stackexchange. COM / VRAGEN / 315812 / Why-DOS-ARGV-omvat-de-programmeernaam / 315817

Runnable Posix execveVoorbeeld waar argv[0] !=uitvoerbare naam

Andere noemde exec, maar hier is een voorbeeld van het fruit.

a.c

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

b.c

#include <stdio.h>
int main(int argc, char **argv) {
    puts(argv[0]);
}

Dan:

gcc a.c -o a.out
gcc b.c -o b.out
./a.out

Geeft:

yada yada

Ja, argv[0]kan ook zijn:

Getest op Ubuntu 16.10.


Antwoord 6, autoriteit 2%

Op deze paginastaat:

Het element argv[0] bevat normaal gesproken de naam van het programma, maar hier mag niet op worden vertrouwd – het is hoe dan ook ongebruikelijk dat een programma zijn eigen naam niet kent!

Andere pagina’s lijken echter te bevestigen dat het altijd de naam is van het uitvoerbare bestand. Dezestelt:

Je zult merken dat argv[0] het pad en de naam van het programma zelf is. Hierdoor kan het programma informatie over zichzelf ontdekken. Het voegt ook nog een toe aan de reeks programmaargumenten, dus een veelvoorkomende fout bij het ophalen van opdrachtregelargumenten is om argv[0] te pakken als je argv[1] wilt.


Antwoord 7, autoriteit 2%

Ik weet niet zeker of het een bijna universele conventie of een standaard is, maar je moet je er hoe dan ook aan houden. Ik heb het echter nooit buiten Unix en Unix-achtige systemen zien misbruiken. In Unix-omgevingen – en misschien vooral vroeger – kunnen programma’s significant verschillend gedrag vertonen, afhankelijk van de naam waaronder ze worden aangeroepen.

BEWERKT: ik zie uit andere berichten op hetzelfde moment als de mijne dat iemand heeft vastgesteld dat het van een bepaalde standaard komt, maar ik weet zeker dat de conventie al lang ouder is dan de standaard.


Antwoord 8

Als je een Amiga-programma start via Workbench, wordt argv[0] niet ingesteld, alleen door CLI.

Other episodes