Frage

Was ist der Vorteil von malloc (neben dem NULL Return on failure) über statische Arrays? Das folgende Programm wird essen alle meine RAM und starten Swap-Füllung nur dann, wenn die Schleifen unkommentiert sind. Es stürzt nicht ab.

...

#include <stdio.h>

unsigned int bigint[ 1u << 29 - 1 ];
unsigned char bigchar[ 1u << 31 - 1 ];

int main (int argc, char **argv) {
  int i;
/*   for (i = 0; i < 1u << 29 - 1; i++) bigint[i] = i; */
/*   for (i = 0; i < 1u << 31 - 1; i++) bigchar[i] = i & 0xFF; */

  getchar();
  return 0;
}

...

Nach einigen Versuch und Irrtum ich die oben gefunden ist die größte statische Array erlaubt auf meinem 32-Bit-Intel-Rechner mit GCC 4.3. Ist dies eine Standardgrenze, ein Compiler-Limit, oder eine Maschine Grenze? Anscheinend kann ich so viele von ihnen, wie ich will. Es wird segfault, aber nur, wenn ich fragen Sie nach (und versuchen, verwenden) mehr als malloc würde mich trotzdem geben.

Gibt es eine Möglichkeit, wenn ein statisches Array zu bestimmen tatsächlich zugeteilt wurde und sicher zu bedienen?

EDIT: Ich bin interessiert, warum malloc verwendet wird, um den Haufen, anstatt dass das virtuelle Speichersystem umgehen zu verwalten. Anscheinend kann ich Größe ein Array zu oft die Größe glaube ich, ich brauche und das virtuelle Speichersystem wird nur im RAM halten, was notwendig ist. Wenn ich schreibe nie z.B. das Ende (oder Anfang) diese großen Arrays dann wird das Programm nicht den physischen Speicher verwenden. Außerdem, wenn ich an jeden Ort schreiben kann dann etwas macht malloc neben einen Zeiger in dem Heap erhöhen oder um vorherige Zuweisungen im gleichen Prozess suchen?

Anmerkung der Redaktion: 1 << 31 href="https://stackoverflow.com/questions/26192284/why-does-1-31-31-result-in-1/"> Ursachen undefiniertes Verhalten wenn int 32-Bit ist, so habe ich die Frage 1u lesen geändert. Die Absicht der Frage geht es um die Zuweisung großen statischen Puffer zu stellen.

War es hilfreich?

Lösung

Nun, aus zwei Gründen wirklich:

  1. Aufgrund der Portabilität, da einige Systeme der virtuellen Speicherverwaltung nicht für Sie tun.

  2. Sie müssen zwangsläufig dieses Array in kleinere Stücke aufzuteilen für sie nützlich zu sein, dann den Überblick über alle Stücke zu halten, dann schließlich, wie Sie beginnen „befreien“ einige der Stücke des Arrays Sie keine mehr benötigen Sie das Problem der Speicherfragmentierung getroffen.

Alles in allem werden Sie eine Menge Speicher-Management-Funktionalität der Umsetzung am Ende (eigentlich ziemlich die malloc Neuimplementierung) ohne den Vorteil der Portabilität.

Daher sind die Gründe:

  • Code-Portabilität über Memory-Management-Verkapselung und Standardisierung.

  • Persönliche Produktivitätssteigerung durch die Art der Wiederverwendung von Code.

Andere Tipps

mit malloc können Sie wachsen und Ihr Array schrumpfen. Es wird dynamisch, so dass Sie genau für zuordnen können, was Sie benötigen

Diese benutzerdefinierte Speicherverwaltung aufgerufen wird, denke ich. Sie können das tun, aber Sie werden sich selbst, dass Teil des Speichers verwalten müssen. Sie würden Ihren eigenen malloc () woring über diesen Brocken aufzuwickeln schreiben.

In Bezug auf:

  

Nach einigem Versuch und Irrtum fand ich die   oben ist die größte statische Array   erlaubt auf meiner 32-Bit-Intel-Maschine   mit GCC 4.3. Ist das ein Standard   Limit, ein Compiler-Limit, oder eine Maschine,   begrenzen?

Eine obere Grenze wird davon abhängen, wie die 4 GB (32-Bit) virtuellen Adressraum zwischen User-Space und Kernel-Raum verteilt. Für Linux, glaube ich, das häufigste Partitionierungsschema einen 3 GB Adressbereich für User-Space und einen 1 GB Adressbereich für Kernel-Space hat. Die Unterteilung ist konfigurierbar, um Kernel-build-time, 2GB / 2 GB und 1 GB / 3 GB Splits ist ebenfalls im Einsatz. Wenn die ausführbare Datei geladen wird, muss virtueller Adressraum für jedes Objekt zugewiesen werden, unabhängig davon, ob reale Speicher zugeordnet wird es wieder auf.

Unter Umständen können Sie diese gigantische Array in einem Kontext zuordnen, andere aber nicht. Zum Beispiel, wenn Ihr Array ist Mitglied einer Struktur und Sie wollen um die Struktur zu übergeben. Einige Umgebungen haben eine 32K Grenze auf struct Größe.

Wie bereits erwähnt, können Sie auch die Größe Ihrer Speicher genau zu verwenden, was Sie brauchen. Es ist wichtig, in leistungskritischen Kontexten nicht in den virtuellen Speicher Paging geführt werden, wenn es vermieden werden kann.

Es gibt keine Möglichkeit zu freier Stack Zuteilung andere als außerhalb des Gültigkeitsbereiches gehen. Also, wenn Sie tatsächlich globale Zuweisung verwenden und VM hat man wirklich hart Speicher Alloc wird zugewiesen und bleiben dort, bis Ihr Programm abläuft. Dies bedeutet, dass jeder Prozess nur wachsen darin Nutzung des virtuellen Speichers ist (Funktionen lokale Stapelzuordnungen haben, und denen wird „befreit“ werden).

Sie können nicht „halten“, um den Stapelspeicher, sobald sie außerhalb des Geltungsbereichs der Funktion geht, wird es immer befreit. So müssen Sie wissen, wie viel Speicher Sie bei der Kompilierung verwendet wird.

Was dann darauf an, wie viele int foo [1 << 29] 's Sie haben können. Da erste ganzen Speicher in Anspruch nimmt (auf 32-Bit) und ist dann (läßt Lüge: 0x000000) die zweiten auf 0xffffffff oder thereaobout lösen wird. Dann würde das dritte, was beheben? Etwas, das 32-Bit-Zeiger nicht ausdrücken können. (Denken Sie daran, dass die Stapel Reservierungen sind teilweise bei compiletime gelöst, teilweise Laufzeit, über Versetzungen, wie weit der Offset-Stapel geschoben wird, wenn Sie diese oder jene Variable Alloc).

So ist die Antwort ziemlich viel ist, dass, wenn Sie int foo [1 << 29] Sie jede zumutbare Tiefe von Funktionen mit anderen Variablen lokalen Stack mehr haben können nicht.

sollte wirklich Sie tun dies vermeiden, wenn Sie wissen, was Sie tun. Versuchen Sie, nur Anfrage so viel Speicher wie Sie benötigen. Auch wenn es nicht in der Art und Weise von anderen Programmen kann es Chaos seine Selbst den Prozess verwendet oder bekommen werden. Es gibt zwei Gründe dafür. Zunächst auf bestimmte Systeme, insbesondere diejenigen 32bit kann Adreßraum verursachen vorzeitig in seltenen Fällen ausgeschöpft. Zusätzlich haben viele Kerne eine Art pro Prozess Begrenzung vorbehalten / virtual / sie nicht in Gebrauch Speicher. Wenn Ihr Programm für den Speicher an den Punkten in der Laufzeit fragt kann der Kernel den Prozess töten, wenn es fragt Speicher reserviert werden, dass diese Grenze überschreitet. Ich habe Programme gesehen, die entweder abgestürzt oder aufgrund eines gescheiterten malloc verlassen, weil sie GB Arbeitsspeicher sind reserviert, während nur wenige MB verwendet wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top