Warum ist malloc wirklich nicht deterministisch? (Linux / Unix)

8

malloc gibt nicht garantiert 0-Speicher zurück. Die herkömmliche Weisheit ist nicht nur das, sondern dass der Inhalt des Speichers malloc zurückkehrt, ist eigentlich nicht deterministisch , z openssl verwendete sie für zusätzliche Zufälligkeit .

Soweit ich weiß, ist malloc jedoch auf brk / sbrk aufgebaut, die "0" Speicher zurückgeben. Ich kann sehen, warum der Inhalt von malloc möglicherweise nicht ist, z. von früher free 'd Speicher, aber warum sollten sie nichtdeterministisch in " normale "Singlethread-Software?

  1. Ist die konventionelle Weisheit wirklich wahr (unter der Annahme der gleichen Binärdatei und Bibliotheken)
  2. Wenn ja, warum?

Bearbeiten Mehrere Leute haben geantwortet, warum der Speicher nicht-0 sein kann, was ich bereits in der obigen Frage erklärt habe. 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. Anders ausgedrückt: warum könnte es bei jeder Ausführung der Binärdatei unterschiedliche Inhalte haben.

    
Oleg2718281828 28.06.2012, 19:34
quelle

10 Antworten

2

Ich denke, dass die Annahme, dass es nicht deterministisch ist, einfach falsch ist, besonders wenn Sie nach einem Kontext ohne Threads fragen. (In einem Threaded-Kontext aufgrund der Planung von Alea könnten Sie einige Nicht-Determinismus haben).

Probier es einfach aus. Erstellen Sie eine sequentielle, deterministische Anwendung, die

  • macht eine ganze Reihe von Zuweisungen
  • füllt den Speicher mit einem Muster, zB füllen Sie ihn mit dem Wert eines Zählers
  • Geben Sie jede zweite dieser Zuweisungen frei
  • weist den gleichen Betrag neu zu
  • Durchlaufen Sie diese neuen Zuweisungen und registrieren Sie den Wert des ersten Bytes in einer Datei (als Textnummern 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.

    
Jens Gustedt 28.06.2012, 20:22
quelle
11

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

z. Bedenken Sie das

%Vor%

Ist eine gültige Implementierung von malloc.

    
Mehrdad 28.06.2012 19:38
quelle
4

Die Anfangswerte von Speicher, die von malloc zurückgegeben werden, sind nicht spezifiziert, was bedeutet, dass die Spezifikationen der C- und C ++ - Sprachen keine Einschränkungen bezüglich der Rückgabewerte enthalten. Dies erleichtert die Implementierung der Sprache auf verschiedenen Plattformen. Es mag zwar wahr sein, dass in Linux malloc mit brk und sbrk implementiert ist und der Speicher sollte auf Null gesetzt werden (ich bin mir nicht mal sicher, dass dies übrigens auch wahr ist), vielleicht auf anderen Plattformen eine eingebettete Plattform, es gibt keinen 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 der Speicher von malloc auch dann nicht benötigt wird, wenn der Speicher des Betriebssystems zunächst auf Null gesetzt wird.

Die gängige Meinung, dass die Werte nichtdeterministisch sind, ist wahrscheinlich eine gute, weil Sie feststellen müssen, dass in jedem Speicher, den Sie zurückerhalten, möglicherweise Mülldaten enthalten sind, 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 suggerieren gibt.

Wenn Sie möchten, dass der Speicher auf Null gesetzt wird, verwenden Sie stattdessen calloc .

Hoffe, das hilft!

    
templatetypedef 28.06.2012 19:40
quelle
3

malloc ist auf vielen Systemen definiert, die in C / C ++ programmiert werden können, einschließlich vieler Nicht-UNIX-Systeme und vieler Systeme, denen das Betriebssystem insgesamt fehlt. Wenn malloc erforderlich ist, um den Speicher auf Null zu setzen, wird die C-Philosophie, CPU so viel wie möglich zu speichern, nicht akzeptiert.

Der Standard bietet eine Nullsetzung cal 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.

    
dasblinkenlight 28.06.2012 19:39
quelle
3

Der von malloc zurückgegebene Speicher wird nicht auf Null gesetzt (oder vielmehr ist garantiert nicht auf Null gesetzt), weil er 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.

Zufälligerweise wird der von malloc zurückgegebene Speicher bei der ersten Zuweisung auf Null gesetzt, weil ein Betriebssystemkern nicht das Risiko eingehen kann, Prozessdaten zu geben, die zuvor einem anderen Prozess gehörten. Wenn das Betriebssystem auf einer neuen Seite Fehler aufweist, wird daher immer nur eine zurückgesetzt, die auf Null gesetzt wurde. Dies ist jedoch völlig unabhängig von malloc .

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

    
Damon 28.06.2012 19:40
quelle
1

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

    
Ned Batchelder 28.06.2012 19:39
quelle
1

Sogar single-threaded Code kann malloc dann frei dann malloc tun und vorher verwendeten Speicher, der nicht Null ist, zurückbekommen.

    
Alan Stokes 28.06.2012 19:39
quelle
1

Es gibt keine Garantie, dass brk / sbrk 0 ausgegebene Daten zurückgibt; Dies ist ein Implementierungsdetail. Es ist im Allgemeinen eine gute Idee für ein Betriebssystem, dies zu tun, um die Möglichkeit zu verringern, dass vertrauliche Informationen von einem Prozess in einen anderen Prozess gelangen, aber nichts in der Spezifikation sagt, dass dies der Fall sein wird / p>

Auch die Tatsache, dass malloc zusätzlich zu brk / sbrk implementiert wird, ist ebenfalls implementierungsabhängig und kann sogar basierend auf der Größe der Zuweisung variieren. Zum Beispiel haben große Zuweisungen unter Linux traditionell mmap anstelle von / dev / zero verwendet.

Grundsätzlich können Sie sich weder auf malloc() ed-Bereiche verlassen, die Müll enthalten, noch darauf, dass sie all-0 sind, und kein Programm sollte die eine oder andere Art davon übernehmen.

    
fluffy 28.06.2012 19:39
quelle
0

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

Wenn ich nach Wandflächen suche, um ein Wandbild zu malen, ist es mir egal, ob es weiß ist oder mit alten Graffiti bedeckt ist, da ich es grundieren und übermalen werde. 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.

    
matchdav 28.06.2012 19:56
quelle
-1

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

Stellen Sie sich vor, wenn Sie Ihre Anwendung und malloc () zum ersten Mal ausführen, erhalten Sie 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 die gleiche Adresse gibt, aber jetzt gibt es dort einen anderen Müll, den das vorherige Programm vielleicht geschrieben hat.

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

Es ist sehr deterministisch.

    
Leonardo 28.06.2012 20:22
quelle