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!
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.
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.
-
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.
-
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.
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.
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
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.
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 vonexecve
-, einschließlich seiner Argumente (dhargv
), ist viel begrenzter (normalerweise einige Megabyte). Soargc
ist weniger als ein paar Millionen und ich habe noch nie von einem Betriebssystem gehört, woargc
könnte in der Nähe seinINT_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 solltesize_t
.– Steve Jessop
22. Januar 2015 um 10:43 Uhr