Ich war in SO unterwegs und habe diese Frage gesehen . Dann begann ich mich zu fragen, ob ich argc überlaufen kann.
Standard sagt, dass argv[argc]
dies ein Nullzeiger sein muss, aber dies ist falsch, wenn argc überläuft.
(I schrieb ein kleines C - Programm und einen Python - Skript , es zu testen , sondern ein bekommt MemoryError
.)
Vielen Dank!
Begründung für den internationalen Standard - Programmiersprachen - C §5.1.2.2.1 Programmstart
Die Spezifikation von
argc
undargv
als Argumente zurmain
Anerkennung umfangreicher früherer Praktiken.argv[argc]
muss ein Nullzeiger sein, um eine redundante Prüfung für das Ende der Liste bereitzustellen, auch auf der Grundlage der gängigen Praxis.
c
integer-overflow
Bora M. Alper
quelle
quelle
Standard says that argv[argc] must be a null pointer but this will be false if argc overflow
- Ich habe dies als "Lass Argc nicht überlaufen" gelesen. ("Doktor, es tut weh, wenn ich das tue")main
-as, der vonexecve
- einschließlich seiner Argumente (dhargv
) installiert wurde , viel eingeschränkter (normalerweise einige Megabyte). Alsoargc
ist weniger als ein paar Millionen und ich habe noch nie von einem Betriebssystem gehört, das inargc
der Nähe sein könnteINT_MAX
argc
sollten Sie Typ habensize_t
.Antworten:
Nach dem Standard
Also, aus Ihrem Zitat:
Daher
argc
kann nicht überlaufen, weil dann die obige Aussage würde nicht wahr sein.In der Praxis
In der Praxis ist die Gesamtgröße der an ein Programm übergebenen Argumente begrenzt.
Auf meinem Linux / x64-System:
Daher beträgt die Gesamtargumentgröße etwa 2 Megabyte und
argc
kann nicht überlaufen. Ich glaube, diese Grenze misst eine Kombination der Gesamtdaten inargv
und der Umgebung. Wenn Sie diese Grenze überschreiten, wenn Sie versuchen, einen Befehl auszuführen,exec()
schlägt dies fehlE2BIG
. Vonman 2 execve
:Ich glaube, dass die ~ 2-Megabyte-Grenze 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 wäre, wenn
ARG_MAX
sie wirklich groß wären ?Okay, nehmen wir an, Sie befinden sich auf einem alten / seltsamen System, also
int
16 Bit, und ARG_MAX liegt weit über 2 15 , was ansonsten durchaus vernünftig ist. Angenommen, Sie rufenexecve()
mit mehr als 2 bis 15 Argumenten auf. Die Implementierung hat zwei Möglichkeiten.Es kann
argc
zu einem Überlauf kommen ... im Grunde genommen können Sie Ihre Daten wegwerfen, sicherstellen, dass das von Ihnen ausgeführte Programm auf unerwartete und wahrscheinlich fehlerhafte Weise ausgeführt wird, und gegen den C-Standard verstoßen. Am schlimmsten ist, dass der Fehler still ist, sodass Sie es möglicherweise nie erfahren.Oder es kann einfach Rückkehr
EOVERFLOW
ausexecve()
, die Sie darüber informiert , dass es einfach nicht , ein Bild mit , dass viele Parameter ausführen. Nun, die POSIX / SUS-Standards erwähnen nichts über dieses Fehlerergebnis ... aber ich vermute, das liegt einfach daran, dass die Standardschreiber nie erwartet habenARG_MAX
, größer als zu seinINT_MAX
.Option 2 ist die einzig vernünftige Option. Wenn Ihr System irgendwie Option 1 wählt, ist diese defekt 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 15 Parameter an ein Programm zu übergeben.
quelle
argv[argc]
, ein Nullzeiger zu sein, impliziert die Anforderung,ARG_MAX
klein genug zu setzen ,argc
damit kein Überlauf möglich ist.In der Praxis können Sie nicht. Die meisten Systeme begrenzen die Gesamtgröße von
argv
und relativ niedrigenvp
. Grenzwerte zwischen zehn und Hunderten von KB sind keine Seltenheit. Unter http://www.in-ulm.de/~mascheck/various/argmax/ finden Sie eine einigermaßen umfassende Auflistung der Grenzwerte für verschiedene Betriebssysteme.quelle
Ich habe es 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 benutzte ich eine große Zip-Datei
⚡⚡⚡ ls -h bigfile -rw-r--r-- 1 ehwas ehwas 355M Jan 22 16:54 bigfile
Lesen Sie dann die Datei als Parameter für das Testprogramm:
Ergebnis:
5 minutes nothing happend, then everything froze
Dann habe ich eine kleinere Datei ausprobiert:
⚡⚡⚡ 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
quelle
Wie im Standard angegeben, muss argv [argc] ein gültiger Wert sein.
Befindet sich die Laufzeitumgebung in einer Situation, in der dies nicht garantiert werden kann, sollte das Programm nicht gestartet werden.
quelle