2010-09-24 7 views
6

Hier ist das Problem: your program temporarily uses some sensitive data and wants to erase it when it's no longer needed. Die Verwendung von std::fill() für sich selbst wird nicht immer helfen - der Compiler könnte entscheiden, dass der Speicherblock nicht später zugegriffen wird, so dass es Zeitverschwendung ist, zu löschen und Löschcode zu entfernen.Werden mit "Zeiger auf flüchtig" Compiler-Optimierungen jederzeit verhindert?

User ybungalobill schlägt using volatile keyword:

{ 
    char buffer[size]; 
    //obtain and use password 
    std::fill_n((volatile char*)buffer, size, 0); 
} 

Die Absicht ist, dass die volatile Schlüsselwort der Compiler versuchen wird nicht beim Anblick den Anruf zu std::fill_n() zu beseitigen.

Wird volatile Schlüsselwort immer verhindern, dass der Compiler von einem solchen Speicher die Codeeliminierung verändert?

+0

Hmmm, ich denke, dass es nicht die genaue Situation ist. Hier weiß der Compiler, dass der Speicher auf Stack zugeordnet ist, da nicht. (so kann es auf ein Speicher-Mapped-Register zeigen) – ybungalobill

+0

Ich wollte eine ähnliche Frage bezüglich dieser Antwort stellen. Lustig, wie eine Sorge viele andere interessante Fragen aufwerfen kann;) Hier ist meine +1. – ereOn

+0

Versuchen Sie, den Puffer als 'volatile char buffer [size]; 'zu deklarieren, anstatt ihn in den Aufruf von' std :: fill_n' zu werfen. –

Antwort

2

Der Compiler kann Ihren Code frei optimieren, da buffer kein flüchtiges Objekt ist.

Der Standard erfordert nur einen Compiler, um die Semantik für flüchtige Objekte strikt einzuhalten. Hier ist, was C++ 03 sagt

Die am wenigsten Anforderungen an eine konforme Implementierung sind:

  • An Sequenzpunkte, flüchtige Objekte sind stabil in dem Sinne, dass die bisherigen Auswertungen sind vollständig und spätere Auswertungen haben noch nicht aufgetreten. [...]
  • ]

und

Das beobachtbare Verhalten der abstrakten Maschine ist die Folge von liest und schreibt auf flüchtige Daten und Anrufe Bibliothek I/O-Funktionen

In Ihrem Beispiel, was Sie haben, liest und schreibt flüchtige lvalues ​​zu nichtflüchtigen Objekten. C++ 0x hat den oben zitierten zweiten Text entfernt, weil er überflüssig ist. C++ 0x sagt nur

die am wenigsten Anforderungen an eine konforme Implementierung sind.

  • Zugang zu flüchtigen Objekte werden nach den Regeln der abstrakten Maschine streng ausgewertet [...]

Diese zusammen werden als beobachtbares Verhalten des Programms bezeichnet.

Während man argumentieren kann, dass „feste Daten“ vielleicht „von flüchtigen lvalues ​​griffenen Daten“ bedeuten könnten, die noch eine ganze Strecke sein würde, die C++ 0x Formulierung alle Zweifel an Ihrem Code entfernt und eindeutig erlaubt Implementierungen um es zu optimieren.

Aber wie die Leute auf mich hingewiesen haben, spielt es in der Praxis wahrscheinlich keine Rolle. Ein Compiler, der solch eine Sache optimiert, wird höchstwahrscheinlich gegen die Absicht des Programmierers gehen (warum hätte jemand sonst einen Zeiger auf flüchtig) und würde daher wahrscheinlich einen Fehler enthalten. Dennoch habe ich Compiler-Anbieter erlebt, die diese Absätze zitiert haben, als sie mit Fehlerberichten über ihre übermäßig aggressiven Optimierungen konfrontiert wurden. Am Ende ist volatile inhärent plattformspezifisch und Sie sollten das Ergebnis trotzdem noch einmal überprüfen.

+1

_Warum neigen diese Regeln dazu, mit Wörtern zu spielen? – Pooria

3

Vom letzten C++ 0x Entwurf [intro.execution]:

8 Die am wenigsten Anforderungen an eine konforme Implementierung sind:

- Zugriff auf flüchtige Objekte werden streng ausgewertet nach die Regeln der abstrakten Maschine.

[...]

12 Zugriff auf ein Objekt durch einen flüchtigen glvalue bezeichnet (3.10), ein Objekt Modifizieren Aufrufen einer Bibliothek I/O Funktion oder eine Funktion aufruft dass Keinerlei von diese Operationen sind alle Nebenwirkungen, [...]

Also selbst der Code, den Sie bereitgestellt werden, muss nicht optimiert werden.

+2

Zumindest müssen die Nebenwirkungen des Schreibens flüchtige Objekte nicht unter der As-if-Regel entfernt werden, was bedeutet, dass der Code tut, was es soll. Der Compiler ist weiterhin frei, andere Optimierungen in 'fill_n' durchzuführen, wie z. B. Schleifen-Abrollung oder Assembler-Peephole-Optimierungen. – Doug

1

Der Speicherinhalt, den Sie entfernen möchten, wurde möglicherweise bereits aus dem internen Cache Ihrer CPU/Core in den Arbeitsspeicher gelöscht, wo andere CPUs ihn weiterhin sehen können. Nach dem Überschreiben müssen Sie eine Mutex/Memory-Barriere-Anweisung/atomare Operation oder etwas verwenden, um eine Synchronisation mit anderen Kernen auszulösen. In der Praxis wird Ihr Compiler dies wahrscheinlich tun, bevor er irgendwelche externen Funktionen aufruft (Google Dave Butenhofs Post zu volatilem dubiosen Dienstprogramm in Multithreading), also wenn Sie das bald danach tun, dann ist das kein großes Problem. Zusammenfassend: flüchtig wird nicht benötigt.

Verwandte Themen