2012-06-28 4 views
8

malloc ist nicht garantiert, 0'ed Speicher zurück zu geben. Das herkömmliche Wissen ist nicht nur das, sondern dass der Inhalt des Speichers malloc Rückgaben tatsächlich non-deterministic sind, z.B. openssl used them for extra randomness.Warum ist Malloc wirklich nicht deterministisch? (Linux/Unix)

aber soweit ich weiß, ist malloc oben auf brk gebaut/sbrk, die "Rückkehr" 0'ed Speicher tun. Ich kann sehen, warum der Inhalt von was malloc zurückgibt möglicherweise, z. von zuvor kostenlos 'd Speicher, aber warum würden sie non-deterministic in "normalen" Singlethread-Software sein?

  1. ist die konventionelle Weisheit wirklich wahr (vorausgesetzt, die gleiche binäre und Bibliotheken)
  2. Wenn ja, warum?

bearbeiten Mehrere Menschen zu erklären, warum antwortet der Speicher nicht 0 sein kann, die ich bereits in der Frage oben erläutert. Ich frage, warum das Programm, das den Inhalt von malloc zurückgibt, nichtdeterministisch sein kann, d. H. Warum es jedes Mal, wenn es ausgeführt wird, ein anderes Verhalten haben kann (unter der Annahme derselben Binärdatei und Bibliotheken). Nicht-deterministisches Verhalten wird von Nicht-Nullen nicht impliziert. Um es anders auszudrücken: Warum könnte es bei jeder Ausführung der Binärdatei einen anderen Inhalt haben?

+1

Wenn Sie sehen, warum es manchmal nicht Null sein kann, dann müssen Sie bereits verstehen, warum die Rückkehr im Allgemeinen nicht deterministisch ist. In jedem speziellen Fall scheint es, als würde es immer den Null-Speicher zurückgeben, aber im allgemeinen Sinn kann das nicht garantiert werden. – Chad

+0

Wie hängt der Link mit der Frage zusammen? –

+0

Sie könnten auch sagen, dass C nicht nur für normale Singlethread-Software verwendet wird ... – Mehrdad

Antwort

2

Ich denke, dass die Annahme, dass es nicht deterministisch ist, einfach falsch ist, vor allem, wenn Sie nach einem Kontext ohne Threads fragen. (In einem Threaded-Kontext aufgrund der Planung von Alea könnte man etwas nicht-deterministisch sein).

Probieren Sie es einfach aus. Erstellen Sie eine sequentielle, deterministisch-Anwendung, die

  • hat eine ganze Reihe von Zuweisungen
  • füllt den Speicher mit einem gewissen Muster, zum Beispiel füllen Sie es mit dem Wert eines Zählers
  • jede Sekunde dieser Zuteilungen frei
  • zuzuteilen neu die gleiche Menge
  • Lauf durch diese neue Zuteilungen und Register den Wert des ersten Bytes in einer Datei (als textuelle Zahlen eins pro Zeile)

führen Sie dieses Programm zweimal aus und registrieren Sie das Ergebnis in zwei verschiedenen Dateien. Meine Idee ist, dass diese Dateien identisch sind.

+0

das ist was ich auch erwarten würde: während Sie nicht wissen, was das Programm ausgeben wird, würde es jedes Mal die gleiche Sache ausgeben (vorausgesetzt, das gleiche binary/Bibliotheken/System), deshalb wird es deterministisch sein. Ich werde diese Antwort akzeptieren, zumindest für den Moment. – Oleg2718281828

+0

Es ist ein etwas anderes Thema (undefiniertes Verhalten), aber die Argumentation gilt auch hier (siehe Basketball Analogie): http://blog.regehr.org/archives/213 – Mehrdad

11

Malloc nicht Garantie Unvorhersehbarkeit ... es garantiert keine Vorhersagbarkeit.

z. Beachten Sie, dass

return 0; 

ist eine gültige Implementierung von malloc.

+1

Mehrdad, meine Frage ist, woher der Nicht-Determinismus kommen würde, und nicht, ob es garantiert ist. – Oleg2718281828

+0

Richtig, und meine Antwort ist, dass es bei Ihrer Implementierung vielleicht gar nicht von irgendwo kommt. Der C-Standard ist nicht nur für Ihre Implementierung gedacht. – Mehrdad

+0

Mehrdad, Sie haben Recht, ich hätte hier klarer sein können: "In Fällen, in denen der Inhalt von malloc nicht deterministisch ist, sagen wir unter Linux, woher kommt dieser Nicht-Determinismus?", Aber das beantwortet meine Frage nicht . – Oleg2718281828

1

Selbst in "normalen" Single-Thread-Programmen wird Speicher mehrfach freigegeben und neu zugewiesen. Malloc wird zu deiner Erinnerung zurückkehren, die du zuvor benutzt hast.

+0

Ned, ja, ich beziehe mich darauf: "Ich kann sehen, warum der Inhalt von was malloc zurückgibt möglicherweise nicht-0 ..." – Oleg2718281828

+0

@ Oleg2718281828: dann weiß ich nicht, was Sie fragen. –

1

Auch single-threaded-Code kann malloc dann frei dann malloc und erhalten Sie zuvor verwendet, nicht-Null-Speicher.

3

malloc ist auf vielen Systemen definiert, die in C/C++ programmiert werden können, einschließlich vieler Nicht-UNIX-Systeme und vieler Systeme, auf denen das Betriebssystem insgesamt fehlt. Die Anforderung malloc, den Speicher auf Null zu stellen, widerspricht der Philosophie von C, CPU so viel wie möglich zu speichern.

Der Standard bietet eine Nullkalibrierung calloc, die verwendet werden kann, wenn Sie den Speicher auf Null setzen müssen. Aber in Fällen, in denen Sie planen, den Speicher selbst zu initialisieren, sobald Sie ihn erhalten, sind die CPU-Zyklen, die dafür aufgewendet wurden, sicherzustellen, dass der Block auf Null gesetzt ist, eine Verschwendung; C-Standard zielt darauf ab, diese Verschwendung so weit wie möglich zu vermeiden, oft auf Kosten der Vorhersagbarkeit.

1

Es kann nicht garantiert werden, dass brk/sbrk 0 out out Daten zurückgibt; Dies ist ein Implementierungsdetail. Es ist in der Regel eine gute Idee für ein Betriebssystem zu tun, um die Möglichkeit zu reduzieren, dass sensible Informationen aus einem Prozess in einen anderen Prozess finden, aber nichts in der Spezifikation sagt, dass es der Fall sein wird.

Auch die Tatsache, dass malloc über brk/sbrk implementiert ist, ist auch implementierungsabhängig und kann sogar basierend auf der Größe der Zuweisung variieren; Zum Beispiel haben große Zuweisungen unter Linux mmap auf/dev/zero verwendet.

Grundsätzlich können Sie sich weder auf malloc() Ed-Regionen verlassen, die Müll enthalten, noch darauf, dass es All-0 ist, und kein Programm sollte die eine oder andere Art davon annehmen.

4

Die Anfangswerte des Speichers, die von malloc zurückgegeben werden, sind nicht angegeben, was bedeutet, dass die Spezifikationen der C- und C++ - Sprachen keine Beschränkungen auf welche Werte zurückgegeben werden können. Dies erleichtert die Implementierung der Sprache auf verschiedenen Plattformen. Während es wahr sein kann, dass in Linux malloc mit brk und sbrk implementiert ist und der Speicher auf Null gesetzt werden sollte (ich bin mir nicht einmal sicher, dass dies unbedingt wahr ist, übrigens), auf anderen Plattformen, vielleicht eine eingebettete Plattform, gibt es keine Grund, dass dies der Fall sein müsste. Beispielsweise möchte ein Embedded-Gerät den Speicher nicht auf Null stellen, da dies CPU-Zyklen und damit Leistung und Zeit kostet. Im Interesse der Effizienz könnte der Speicherzuordner z. B. Blöcke, die zuvor freigegeben worden waren, wieder aufbereiten, ohne sie vorher auf Null zu setzen. Dies bedeutet, dass auch dann, wenn der Speicher vom Betriebssystem zunächst auf Null gesetzt wird, der Speicher von malloc nicht benötigt wird.

Die herkömmliche Weisheit, dass die Werte nichtdeterministisch sind, ist wahrscheinlich eine gute, weil Sie feststellen müssen, dass jeder gespeicherte Speicher Daten enthält, die Ihr Programm zum Absturz bringen könnten. Das heißt, Sie sollten nicht davon ausgehen, dass die Werte wirklich zufällig sind. Sie sollten jedoch erkennen, dass die zurückgegebenen Werte nicht magisch sein werden, was Sie wollen. Sie sind für die korrekte Einrichtung verantwortlich. Angenommen, die Werte sind wirklich zufällig, ist eine wirklich schlechte Idee, da es überhaupt nichts zu sagen gibt.

Wenn Sie Speicher benötigen, der garantiert auf Null gesetzt wird, verwenden Sie stattdessen calloc.

Hoffe, das hilft!

3

Der von malloc zurückgegebene Speicher ist nicht genullt (oder vielmehr garantiert, um genullt zu werden), weil es nicht benötigt wird. Es besteht kein Sicherheitsrisiko bei der Wiederverwendung von nicht initialisiertem Speicher, der aus dem Adressraum oder dem Seitenpool Ihres eigenen Prozesses abgerufen wurde. Du weißt schon, dass es da ist, und du kennst den Inhalt bereits. Es gibt auch kein Problem mit den Inhalten in einem praktischen Sinn, weil Sie es sowieso überschreiben werden.

eventuelle Stich, der Speicher durch malloc zurück wird bei der ersten Zuteilung auf Null gesetzt, weil ein Betriebssystem-Kernel nicht das Risiko des Gebens ein Prozessdaten leisten können, dass ein anderer Prozess zuvor im Besitz. Wenn das Betriebssystem eine neue Seite ausfüllt, wird daher immer nur eine zurückgesetzt, die auf Null gesetzt wurde. Dies steht jedoch in keinem Zusammenhang mit malloc.

(Etwas off-topic: Die Debian-Sicherheitsfrage, die Sie erwähnten, hatte ein paar Implikationen mehr als die Verwendung von nicht initialisiertem Speicher für Zufälligkeiten. Ein Packager, der mit der inneren Funktionsweise des Codes nicht vertraut war und die genauen Auswirkungen nicht kannte ein paar Orte, von denen Valgrind berichtet hatte, vermutlich mit guter Absicht, aber zu verheerenden Auswirkungen, darunter das "zufällige aus dem uneinsichtigen Gedächtnis", aber es war bei weitem nicht das schwerste.)

0

Der einfachste Weg, ich setzen die Antwort denken kann, ist wie folgt:

Wenn ich Platz an der Wand suchen ein Wandbild zu malen, ist mir egal, ob es mit alten Graffiti weiß oder bedeckt ist, Ich werde es grundieren und übermalen. Es ist mir egal, ob ich genug Platz für das Bild habe, und es ist mir wichtig, dass ich nicht über einen Bereich male, der jemand anderem gehört.

So denkt malloc. Das Nullen von Speicher jedes Mal, wenn ein Prozess endet, wäre verschwendeter Rechenaufwand. Es wäre so, als würde man jedes Mal, wenn man mit dem Malen fertig ist, die Wand wieder aufleeren.

-1

Es gibt ein ganzes Ökosystem von Programmen, die in einem Computerspeicher existieren, und Sie können nicht kontrollieren, in welcher Reihenfolge mallocs und frees geschehen.

Stellen Sie sich vor, dass das erste Mal, wenn Sie Ihre Anwendung und malloc() etwas ausführen, gibt es Ihnen eine Adresse mit etwas Müll. Dann wird Ihr Programm heruntergefahren, Ihr Betriebssystem markiert diesen Bereich als frei. Ein anderes Programm nimmt es mit einem anderen malloc(), schreibt viel Zeug und geht dann. Sie führen Ihr Programm erneut aus, es kann passieren, dass malloc() Ihnen dieselbe Adresse gibt, aber jetzt gibt es dort einen anderen Müll, den das vorherige Programm vielleicht geschrieben hat.

Ich weiß eigentlich die Implementierung von malloc() in keinem System und ich weiß nicht, ob es irgendeine Art von Sicherheitsmaßnahme implementiert (wie Randomisierung der zurückgegebenen Adresse), aber ich denke nicht.

Es ist sehr deterministisch.

+0

Betriebssysteme implementieren im Grunde niemals malloc. Die C-Laufzeitbibliothek verwendet dazu eine Form der Heap-Verwaltung zusätzlich zu den Betriebssystemfunktionen. Für gängige moderne Betriebssysteme geben die verwendeten Funktionen virtuellen Speicher zurück und aus Sicherheitsgründen wird fast immer garantiert, dass sie null sind. –

Verwandte Themen