Gibt es eine maximale Länge für ein Array in C ++?
Ist es ein C ++ - Limit oder hängt es von meinem Computer ab? Ist es optimierbar? Kommt es auf den Typ an, aus dem das Array besteht?
Kann ich diese Grenze irgendwie überschreiten oder muss ich nach einer besseren Möglichkeit suchen, Informationen zu speichern? Und was sollte der einfachste Weg sein?
Was ich tun muss, ist long long int auf einem Array zu speichern. Ich arbeite in einer Linux-Umgebung. Meine Frage ist: Was muss ich tun, wenn ich ein Array von N langen langen ganzen Zahlen mit N> 10 Ziffern speichern muss?
Ich brauche das, weil ich einen kryptografischen Algorithmus (wie zum Beispiel den p-Pollard) für die Schule schreibe und diese Wand aus ganzen Zahlen und der Länge der Arrays-Darstellung treffe.
new
oder übergebenen Parameter in der Größe begrenztmalloc
. Auf einen Speicherblock, der größer als ein Array ist, kann über einen Zeiger zugegriffen werden.Niemand erwähnte die Begrenzung der Größe des Stapelrahmens .
Es gibt zwei Stellen, an denen Speicher zugewiesen werden kann:
Die Größenbeschränkung ist hier eine Kombination aus verfügbarer Hardware und der Fähigkeit des Betriebssystems, Speicherplatz zu simulieren, indem andere Geräte verwendet werden, um nicht verwendete Daten vorübergehend zu speichern ( dh Seiten auf die Festplatte zu verschieben).
Die Größenbeschränkung ist hier vom Compiler definiert (mit möglichen Hardwarebeschränkungen). Wenn Sie die Compiler-Dokumentation lesen, können Sie diese Größe häufig anpassen.
Wenn Sie also ein Array dynamisch zuweisen (das Limit ist groß und wird von anderen Posts ausführlich beschrieben.
Wenn das Array auf dem Stapel zugewiesen ist, sind Sie alternativ durch die Größe des Stapelrahmens begrenzt. NB- Vektoren und andere Container haben eine geringe Präsenz im Stapel, aber normalerweise befindet sich der Großteil der Daten auf dem Heap.
quelle
new
odermalloc
).Global Arrays
keine Schönheit ist und am besten vermieden wird, fallen diese nicht unter die Einschränkungen derstack
, und Sie brauchenmalloc
/free
arbeiten nicht mit ihnen.Aus praktischer und nicht aus theoretischer Sicht beträgt auf einem 32-Bit-Windows-System maximal 2 GB Arbeitsspeicher für einen einzelnen Prozess. Sie können das Limit überschreiten, indem Sie ein 64-Bit-Betriebssystem mit viel mehr physischem Speicher verwenden. Ob Sie dies tun oder nach Alternativen suchen, hängt jedoch stark von Ihren beabsichtigten Benutzern und deren Budgets ab. Sie können es auch mit PAE etwas erweitern .
Der Typ des Arrays ist sehr wichtig, da die Standardstrukturausrichtung auf vielen Compilern 8 Byte beträgt, was sehr verschwenderisch ist, wenn die Speichernutzung ein Problem darstellt. Wenn Sie Visual C ++ als Ziel für Windows verwenden, lesen Sie die Direktive #pragma pack , um dies zu überwinden.
Eine andere Sache, die Sie tun müssen, ist zu prüfen, was Ihnen bei Speicherkomprimierungstechniken helfen kann, wie z. B. spärliche Matrizen, spontane Komprimierung usw. Auch dies ist stark anwendungsabhängig. Wenn Sie Ihren Beitrag bearbeiten, um weitere Informationen darüber zu erhalten, was sich tatsächlich in Ihren Arrays befindet, erhalten Sie möglicherweise nützlichere Antworten.
Bearbeiten: Angesichts etwas mehr Informationen zu Ihren genauen Anforderungen scheint Ihr Speicherbedarf unkomprimiert zwischen 7,6 GB und 76 GB zu liegen, was eine ziemlich teure 64-Bit-Box erfordern würde, um als Array im Speicher in C ++ gespeichert zu werden. Es stellt sich die Frage, warum Sie die Daten im Speicher speichern möchten, wo man die Geschwindigkeit des Zugriffs voraussetzt und einen wahlfreien Zugriff zulässt. Der beste Weg, diese Daten außerhalb eines Arrays zu speichern, hängt davon ab, wie Sie darauf zugreifen möchten. Wenn Sie zufällig auf Array-Mitglieder zugreifen müssen, gibt es für die meisten Anwendungen Möglichkeiten, Datenklumpen zu gruppieren, auf die gleichzeitig zugegriffen wird. In großen GIS- und Geodatenbanken werden Daten beispielsweise häufig nach geografischen Gebieten gekachelt. In C ++ - Programmierbegriffen können Sie den Array-Operator [] überschreiben, um bei Bedarf Teile Ihrer Daten aus dem externen Speicher abzurufen.
quelle
Ich würde dem oben Gesagten zustimmen, wenn Sie Ihr Array mit initialisieren
dann ist SIZE durch die Größe einer ganzen Zahl begrenzt. Sie können jedoch jederzeit einen Teil des Speichers mallocieren und einen Zeiger darauf haben, so groß wie Sie möchten, solange malloc nicht NULL zurückgibt.
quelle
int oops[INT_MAX]{0};
Er generiert,C2148 - total size of array must not exceed 0x7fffffff bytes
66%
Speicher, der derzeit verwendet wird, bevor meine App als Debug unter Windows 10 mit VS2017 gestartet wird, habe ich eine undefinierte Grenze für die Größe eines Int-Arrays, mit dem ich initialisieren kann0
. Manchmal kann ich es mit ~ 257k Elementen machen, manchmal bekomme ich einen Stapelüberlauf. Wenn ich meiner App etwas anderes als das Hauptmenü und das Array hinzufüge , sinkt diese Zahl (offensichtlich). Ich musste experimentieren, um diese Zahl zu bestimmen, daher sehe ich nicht, wie man sich auf diese Metrik verlassen kann, ohne die theoretischen Grenzen im luftleeren Raum zu kennen.Um die Antworten zusammenzufassen, zu erweitern und Ihre Frage direkt zu beantworten:
Nein, C ++ legt keine Grenzen für die Dimensionen eines Arrays fest.
Da das Array jedoch irgendwo im Speicher gespeichert werden muss, gelten speicherbezogene Beschränkungen, die von anderen Teilen des Computersystems auferlegt werden. Beachten Sie, dass sich diese Grenzwerte nicht direkt auf die Abmessungen (= Anzahl der Elemente) des Arrays beziehen , sondern auf dessen Größe (= Speicherplatz). Abmessungen ( D ) und in-Speichergröße ( S ) aus einer Anordnung ist nicht das gleiche, wie sie durch den Speicher durch ein einziges Element (genommen in Zusammenhang stehen E ): S = D * E .
JetztE hängt ab von:
"verschwendetem Platz" (Auffüllen) zwischen Elementen führt
Beachten Sie außerdem, dass Sie im Allgemeinen unterschiedliche speicherbezogene Einschränkungen erhalten, wenn Sie die Array-Daten auf dem Stapel (als automatische Variable
int t[N]
:) oder auf dem Heap (dynamische Zuordnung mitmalloc()
/new
oder mithilfe von STL-Mechanismen) oder im statischen Teil des Prozessspeichers (as) zuweisen eine statische Variable :)static int t[N]
. Selbst wenn Sie auf dem Heap zuweisen, benötigen Sie immer noch eine kleine Menge Speicher auf dem Stapel, um Verweise auf die vom Heap zugewiesenen Speicherblöcke zu speichern (dies ist jedoch normalerweise vernachlässigbar).Die Größe des
size_t
Typs hat keinen Einfluss auf den Programmierer (ich gehe davon aus, dass der Programmierer densize_t
Typ für die Indizierung verwendet, da er dafür ausgelegt ist), da der Compiler-Anbietertypedef
einen ganzzahligen Typ verwenden muss, der groß genug ist, um die für die jeweilige Plattform maximal mögliche Speichermenge zu adressieren die Architektur.Die Ursachen für die Speichergrößenbeschränkungen stammen aus
Sie können auf Anwendungsebene nicht "optimiert" werden. Sie können jedoch einen anderen Compiler verwenden (um die Stapelgrößenbeschränkungen zu ändern) oder Ihre Anwendung auf 64-Bit portieren oder auf ein anderes Betriebssystem portieren oder das physische / ändern Konfiguration des virtuellen Speichers der (virtuellen? physischen?) Maschine.
Es ist nicht ungewöhnlich (und sogar ratsam), alle oben genannten Faktoren als externe Störungen und damit als mögliche Ursachen für Laufzeitfehler zu behandeln und Speicherzuordnungsfehler in Ihrem Programmcode sorgfältig zu überprüfen und darauf zu reagieren.
Also schließlich: Während C ++ keine Grenzen setzt, müssen Sie beim Ausführen Ihres Codes immer noch nach ungünstigen speicherbezogenen Bedingungen suchen ... :-)
quelle
Wie viele hervorragende Antworten zeigten, gibt es viele Einschränkungen, die von Ihrer Version des C ++ - Compilers, dem Betriebssystem und den Computereigenschaften abhängen. Ich schlage jedoch das folgende Skript in Python vor, das das Limit auf Ihrem Computer überprüft.
Es verwendet die binäre Suche und prüft bei jeder Iteration, ob die mittlere Größe möglich ist, indem ein Code erstellt wird, der versucht, ein Array der Größe zu erstellen. Das Skript versucht, es zu kompilieren (leider funktioniert dieser Teil nur unter Linux) und die binäre Suche je nach Erfolg anzupassen. Hör zu:
Sie können es auf Ihrem Computer speichern und starten, und es wird die maximale Größe gedruckt, die Sie erstellen können. Für meine Maschine ist es 2305843009213693951.
quelle
Eine Sache, die ich nicht glaube, wurde in den vorherigen Antworten erwähnt.
Ich spüre immer einen "schlechten Geruch" im Sinne eines Refactorings, wenn Leute solche Dinge in ihrem Design verwenden.
Dies ist ein riesiges Array und möglicherweise nicht die beste Möglichkeit, Ihre Daten sowohl unter Effizienz- als auch unter Leistungsgesichtspunkten darzustellen.
Prost,
rauben
quelle
Wenn Sie mit so großen Daten arbeiten müssen, müssen Sie sie in überschaubare Teile aufteilen. Auf keinem kleinen Computer passt alles in den Speicher. Sie können wahrscheinlich einen Teil der Daten von der Festplatte laden (was auch immer angemessen passt), Ihre Berechnungen und Änderungen daran vornehmen, sie auf der Festplatte speichern und dann wiederholen, bis sie abgeschlossen sind.
quelle
So ärgerlich unspezifisch alle aktuellen Antworten auch sind, sie sind meistens richtig, aber mit vielen Einschränkungen, die nicht immer erwähnt werden. Das Wesentliche ist, dass Sie zwei Obergrenzen haben und nur eine davon tatsächlich definiert ist, also YMMV :
1. Kompilierzeitlimits
Grundsätzlich, was Ihr Compiler erlaubt. Für Visual C ++ 2017 auf einer x64 Windows 10-Box ist dies meine maximale Grenze zur Kompilierungszeit, bevor die 2-GB-Grenze erreicht wird.
Wenn ich das stattdessen tun würde,
Ich würde bekommen:
Ich bin nicht sicher, wie 2G mit
255999996
/ korreliert7
. Ich habe beide Zahlen gegoogelt, und das einzige, was ich finden konnte, das möglicherweise damit zusammenhängt, war dieses * nix Q & A über ein Präzisionsproblem mitdc
. In beiden Fällen scheint es keine Rolle zu spielen, welchen Typ von int-Array Sie füllen möchten, sondern nur, wie viele Elemente zugewiesen werden können.2. Laufzeitlimits
Ihr Stapel und Ihr Heap haben ihre eigenen Einschränkungen. Diese Grenzwerte sind sowohl Werte, die sich basierend auf den verfügbaren Systemressourcen ändern, als auch die "Schwere" Ihrer App. Mit meinen aktuellen Systemressourcen kann ich beispielsweise Folgendes ausführen:
Aber wenn ich es nur ein bisschen optimiere ...
Bam! Paketüberfluss!
Und nur um die ganze Schwere Ihres App-Punkts zu beschreiben, war dies gut zu gehen:
Dies verursachte jedoch einen Stapelüberlauf:
quelle
Ich bin überrascht, dass die max_size () -Mitgliedsfunktion von std :: vector hier nicht erwähnt wurde.
Wir wissen, dass dies
std::vector
als dynamisches Array unter der Haube implementiert ist. Dahermax_size()
sollte die maximale Länge eines dynamischen Arrays auf Ihrem Computer sehr genau angegeben werden.Das folgende Programm erstellt eine Tabelle mit der ungefähren maximalen Array-Länge für verschiedene Datentypen.
Unter meinem MacOS (Clang Version 5.0.1) erhalte ich Folgendes:
Auf ideone gcc 8.3 bekomme ich:
Es ist zu beachten, dass dies eine theoretische Grenze ist und dass auf den meisten Computern der Speicher knapp wird, bevor Sie diese Grenze erreichen. Zum Beispiel sehen wir, dass für type
char
ongcc
die maximale Anzahl von Elementen gleich dem Maximum von iststd::size_t
. Wenn wir dies versuchen , erhalten wir den Fehler:Wie @MartinYork hervorhebt, ist die maximale Größe für statische Arrays durch die Größe Ihres Stapels begrenzt.
quelle
Wie bereits erwähnt, ist die Arraygröße durch Ihre Hardware und Ihr Betriebssystem (man ulimit) begrenzt. Ihre Software kann jedoch nur durch Ihre Kreativität eingeschränkt sein. Können Sie beispielsweise Ihr "Array" auf der Festplatte speichern? Benötigen Sie wirklich lange, lange Ints? Benötigen Sie wirklich ein dichtes Array? Benötigen Sie überhaupt ein Array?
Eine einfache Lösung wäre die Verwendung von 64-Bit-Linux. Selbst wenn Sie physisch nicht über genügend RAM für Ihr Array verfügen, können Sie mit dem Betriebssystem Speicher zuweisen, als ob Sie dies tun würden, da der für Ihren Prozess verfügbare virtuelle Speicher wahrscheinlich viel größer als der physische Speicher ist. Wenn Sie wirklich auf alles im Array zugreifen müssen, müssen Sie es auf der Festplatte speichern. Abhängig von Ihren Zugriffsmustern gibt es möglicherweise effizientere Möglichkeiten, dies zu tun (z. B. die Verwendung von mmap () oder das einfache sequentielle Speichern der Daten in einer Datei (in diesem Fall würde 32-Bit-Linux ausreichen)).
quelle
Ich würde dies umgehen, indem ich ein dynamisches 2D-Array erstelle:
Mehr dazu hier https://stackoverflow.com/a/936702/3517001
quelle