Kann argc überlaufen?

Lesezeit: 5 Minuten

Benutzeravatar von Bora M. Alper
Bora M. Alper

Ich bin in SO gewandert und habe diese Frage gesehen. Dann begann ich mich zu fragen, ob ich argc überlaufen lassen kann.

Standard sagt das argv[argc] muss ein Nullzeiger sein, aber dies ist falsch, wenn argc überläuft.

(ICH schrieb Ein kleines C-Programm und ein Python-Skript zum Testen bekamen sie aber ein MemoryError.)

Vielen Dank!


Begründung für International Standard – Programmiersprachen – C §5.1.2.2.1 Programmstart

Die Angabe von argc und argv als Argumente dazu main erkennt umfangreiche Vorpraxis an. argv[argc] muss ein Nullzeiger sein, um eine redundante Prüfung für das Ende der Liste bereitzustellen, ebenfalls auf der Grundlage allgemeiner Praxis.

  • Standard says that argv[argc] must be a null pointer but this will be false if argc overflow — Ich lese dies als “Argc nicht überlaufen lassen.” (“Doktor, es tut weh, wenn ich das tue”)

    – Robert Harvey

    21. Januar 2015 um 19:33 Uhr


  • Auf POSIX und auf den meisten Linux-Systemen ist der anfängliche Stack von main – wie installiert von execve-, einschließlich seiner Argumente (dh argv), ist viel begrenzter (normalerweise einige Megabyte). So argc ist weniger als ein paar Millionen und ich habe noch nie von einem Betriebssystem gehört, wo argc könnte in der Nähe sein INT_MAX

    – Basile Starynkevitch

    21. Januar 2015 um 19:35 Uhr


  • Die Implementierung wird in einem solchen Fall wohl eine systemspezifische Grenze haben, die es unmöglich macht, 2^15 Argumente an ein Programm zu übergeben

    – Nr

    21. Januar 2015 um 19:40 Uhr

  • Nun, ich tippe sie sicherlich nicht ein 🙂

    – Martin Jakob

    21. Januar 2015 um 20:17 Uhr

  • Moment mal, was meine ich mit „ich wäre nicht überrascht“. Jede LP64- oder LLP64-Architektur passt, also Windows oder Linux. Du brauchst allerdings viel RAM. Ich nehme an, wenn Sie bei Null anfangen, argc Typ haben sollte size_t.

    – Steve Jessop

    22. Januar 2015 um 10:43 Uhr


Benutzeravatar von Dietrich Epp
Dietrich Ep

Nach Norm

Also aus deinem Zitat:

argv[argc] muss ein Nullzeiger sein

Deswegen, argc kann nicht überlaufen, denn dann wäre die obige Aussage nicht wahr.

In der Praxis

In der Praxis ist die Gesamtgröße der an ein Programm übergebenen Argumente begrenzt.

Auf meinem Linux/x64-System:

$ getconf ARG_MAX
2097152

Daher beträgt die gesamte Argumentgröße etwa 2 Megabyte und argc kann nicht überlaufen. Ich glaube, diese Grenze misst eine Kombination der gesamten Daten in argv und die Umwelt. Wenn Sie dieses Limit überschreiten, wenn Sie versuchen, einen Befehl auszuführen, exec() wird mit scheitern E2BIG. Aus man 2 execve:

E2BIG  The total number of bytes in the environment (envp) and argument
       list (argv) is too large.

Ich glaube, dass das ~2-Megabyte-Limit auf meinem System im Vergleich zu anderen Systemen relativ großzügig ist. Mein OS X-System meldet ein Limit von ~260 KB.

Aber was wenn ARG_MAX waren wirklich groß?

Okay, nehmen wir an, Sie haben ein altes/seltsames System int ist 16 Bit und ARG_MAX ist weit über 2fünfzehn, was ansonsten ganz vernünftig ist. Nehmen wir nun an, Sie rufen auf execve() mit mehr als 2fünfzehn Argumente. Die Implementierung hat zwei Möglichkeiten.

  1. Es kann zulassen argc zum Überlaufen bringen … im Grunde genommen Ihre Daten wegwerfen, sicherstellen, dass das von Ihnen ausgeführte Programm auf unerwartete und wahrscheinlich fehlerhafte Weise ausgeführt wird, und den C-Standard verletzen. Das Schlimmste ist, dass der Fehler still ist, sodass Sie es vielleicht nie erfahren werden.

  2. Oder es kann einfach zurückkehren EOVERFLOW aus execve(), die Sie darüber informiert, dass ein Bild mit so vielen Parametern einfach nicht ausgeführt werden kann. Nun, die POSIX / SUS-Standards erwähnen nichts über dieses Fehlerergebnis … aber ich vermute, dass dies einfach daran liegt, dass die Standardautoren nie damit gerechnet haben ARG_MAX größer sein als INT_MAX.

Option #2 ist die nur vernünftige Möglichkeit. Wenn Ihr System irgendwie Option #1 wählt, dann ist es das gebrochen und Sie sollten einen Fehlerbericht einreichen.

Alternativ könnten Sie versuchen, ein altes Programm auszuführen, das für ein 16-Bit-System kompiliert wurde, aber Sie führen es über eine Art Emulator oder Kompatibilitätsschicht aus. Ich würde erwarten, dass der Emulator oder die Kompatibilitätsschicht eine Fehlermeldung ausgibt, wenn Sie versuchen, mehr als 2 zu übergebenfünfzehn Parameter zu einem Programm.

  • Aber stellen Sie sich vor, Sie befinden sich auf einem System, auf dem das ARG_MAX-Ding ziemlich groß ist (aus welchen Gründen auch immer) und es passieren könnte. Was wäre das für ein Scheitern? Da es immer noch den Standard respektiert, kann es als C-kompatibel bezeichnet werden, aber es könnte auch ein undefiniertes Verhalten auftreten, das der Programmierer nicht verhindern kann. Was ist das für ein Fehler?

    – dhein

    22. Januar 2015 um 12:40 Uhr

  • Ich denke, der Standard hat dort ein undefiniertes Verhalten, da ein signierter Überlauf nicht definiert ist.

    – Sebastian Mach

    22. Januar 2015 um 14:16 Uhr

  • @zaibis Die Voraussetzung für argv[argc] ein Nullzeiger zu sein impliziert eine Setzbedingung ARG_MAX klein genug, dass argc kann nicht Überlauf.

    – zol

    22. Januar 2015 um 16:38 Uhr

In der Praxis nein, das geht nicht. Die meisten Systeme legen eine relativ niedrige Grenze für die kombinierte Gesamtgröße fest argv und envp. Limits im Zehner- bis Hunderterbereich von KB sind keine Seltenheit; sehen http://www.in-ulm.de/~mascheck/various/argmax/ für eine einigermaßen umfassende Auflistung der Beschränkungen auf verschiedenen Betriebssystemen.

  • Diese Liste enthält keine Daten für Windows, aber es gibt Fragen zu SO mit einigen Zahlen.

    – PTwr

    22. Januar 2015 um 7:49 Uhr

Ich habe das versucht:

test.c:

 ⚡⚡⚡  more test.c 
#include <stdio.h>
int main(int argc, char **argv)
{
    printf("argc = %d\n", argc);
    printf("Size of argc = %d\n", sizeof(argc));
    return 0;
}

Dann eine große ZIP-Datei verwendet

 ⚡⚡⚡  ls -h bigfile 
-rw-r--r-- 1 ehwas ehwas 355M Jan 22 16:54 bigfile

Lesen Sie dann die Datei als Parameter in das Testprogramm ein:

⚡⚡⚡  ./test $(more bigfile)

Ergebnis:

5 minutes nothing happend, then everything froze

Dann habe ich es mit einer kleineren Datei versucht:

 ⚡⚡⚡  ls -h notsobigfile 
-rw-r--r-- 1 ehwas ehwas 6.7M Jan 22 17:04 notsobigfile

Und:

 ⚡⚡⚡  ./test $(more notsobigfile)
bash: ./test: Argument list too long

  • Warum eine ZIP-Datei verwenden, um Argumente zu generieren, wenn Sie nur $(seq 1 100000) verwenden können?

    – pflaquerre

    28. Januar 2015 um 19:13 Uhr


  • Habe nicht daran gedacht. Vielen Dank!

    – äh was

    28. Januar 2015 um 21:26 Uhr

Wie vom Standard angegeben, argv[argc] muss ein gültiger Wert sein.

Befindet sich die Laufzeitumgebung also in einer Situation, in der sie dies nicht garantieren kann, sollte sie das Programm nicht starten.

1417330cookie-checkKann argc überlaufen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy