Gibt irgendeine Implementierung von operator new einen Zeiger auf eine Schutzseite für Arrays mit einer Größe von null zurück?

8

Verwandt mit: C ++ new int [0] - wird es Speicher zuweisen?

Der Standard sagt in 5.3.4 / 7:

  

Wenn der Wert des Ausdrucks in einem Direkt-Neudeklarator Null ist, wird die Zuweisungsfunktion aufgerufen, um ein Array ohne Elemente zuzuordnen.

... und in 3.7.3.1/2:

  

Der Effekt der Dereferenzierung eines Zeigers, der als Anforderung für die Größe null zurückgegeben wird, ist nicht definiert.

... noch darf der Zeiger kein Nullzeiger sein.

Da die tatsächliche Dereferenzierung des Zeigers ein nicht definiertes Verhalten ist, gibt eine Implementierung einen Zeiger auf eine Schutzseite zurück? Ich kann mir vorstellen, dass es einfach wäre und Bugs erkennen / die Sicherheit verbessern könnte.

    
Alexander Riccio 22.07.2015, 22:27
quelle

2 Antworten

4

Ich habe mir den (Entwurfs-) Standard angeschaut und konnte nichts finden, was dies ausdrücklich verbietet. Ich würde vermuten, dass die Antwort "nein" ist. Deshalb:

  • Wie Sie sagen, ist new erforderlich, um einen Nicht-Null-Zeiger zurückzugeben.
  • Außerdem muss alles, was zurückgegeben wird, sicher übergeben werden, um es zu löschen.
  • Also funktioniert ein "zufälliger Wert" nicht, weil er die Löschung löscht.
  • Außerdem müssen Sie für jeden Aufruf verschiedene Werte zurückgeben (zumindest bis sie gelöscht werden) - siehe C ++ - Standardabschnitt basic.stc.dynamic.allocation.
  • An dieser Stelle bleibt nur eine Option übrig: "falsche Zeiger" zurückgeben, die durch Löschen als "falsche Zeiger" erkennbar sind.

Eine mögliche Implementierung könnte getan werden, indem ein Bereich von nicht ausgelagertem Speicher reserviert wird, und jedes Mal, wenn jemand den neuen int [0] aufruft, könnte er eine andere Adresse in diesem Bereich zurückgeben (leicht zu tun, wenn der Zuordner einen globalen Zähler oder ähnliches hält) das).

Auf der positiven Seite erhalten Sie die Möglichkeit, Dereferenzierungen bei diesem Zeigertyp sofort zu erkennen. Auf der anderen Seite verlieren Sie die Fähigkeit, Double-Frees zu erkennen, da das Löschen auf Ihrem Pointer effektiv zu einem No-Op wird, und Sie werden für alle normalen Fälle neue und komplexe und langsamere löschen.

Also, weil es schwierig ist, und die Nachteile die Vorteile überwiegen, bin ich ziemlich zuversichtlich, dass niemand das tut.

gcc auf Linux weist nur eine kleine Menge Speicher zu und gibt diese zurück. Ich glaube, das ist so ziemlich ein Standardverfahren.

    
AaronI 22.07.2015, 23:32
quelle
2

Um zu verfolgen, wie viel Speicher freigegeben werden muss, sehen die meisten Zuordner, die ich gesehen oder geschrieben habe, so aus:

%Vor%

Wenn Sie Blöcke mit einer Länge von Null zuweisen, erhalten Sie ein hinterhältiges Wort vor der Adresse, die Ihnen zurückgegeben wird. Dies stellt auch sicher, dass jeder Zuweisung eine eindeutige Adresse zugewiesen wird. Dies ist wichtig, und auf den reservierten Schutzspeicher für Blöcke mit einer Länge von Null zu zeigen, ist mehr eine Verschwendung, da jeder frei testen muss, was meiner Erfahrung nach eine seltene Bedingung ist.

Einige Debugging-Allokatoren enthalten zusätzlichen Overhead, um Double-Frees, Speicherlecks, Guard-Words zum Überlauf früherer Puffer usw. abzufangen. Außerdem kann das Zeigen auf einen magischen Speicher ein solches Debugging schwieriger machen.

    
Gilbert 23.07.2015 00:19
quelle

Tags und Links