Werden konstante Variablen im Nur-Lese-Speicher abgelegt? [duplicate]

Lesezeit: 8 Minuten

Benutzer-Avatar
Oleksiy

Oder gibt es einen anderen Schutz gegen das Ändern?

Es ist sinnvoll, wenn sie sich im Nur-Lese-Speicher befinden – das ist der Grund dafür, sie zu erstellen constRechts?

  • Siehe diese Antwort für ein Beispiel von const volatilewo Nur-Lese-Speicher keinen Sinn machen würde.

    – dyp

    5. August 2013 um 12:30 Uhr

  • Ich bin mir ziemlich sicher, dass in C# alle Verwendungen von a const werden während der Kompilierung durch ihren Wert ersetzt, sodass nichts mehr geändert werden muss. Ich weiß jedoch nicht, ob das ein .NET-Ismus ist oder ob es von C geerbt wurde.

    – Bobson

    5. August 2013 um 13:22 Uhr

  • @Bobson Das ist in C++ unmöglich zu erreichen, weil const Variablen können ihren Wert zur Laufzeit setzen.

    – Juanchopanza

    5. August 2013 um 13:24 Uhr

  • @juanchopanza – Gut zu wissen. Die Unterschiede, die zwischen verschiedenen verwandten Sprachen bestehen, sind faszinierend.

    – Bobson

    5. August 2013 um 13:27 Uhr


  • const int r = rand();

    – Keith Thompson

    10. August 2013 um 1:17 Uhr

const ist ein Konstrukt zur Kompilierzeit und zur Laufzeit nicht bekannt. Es ist nur dazu da, dem Programmierer zu helfen, sein Programm zu verstehen und zu verhindern, dass Fehler eingeführt werden, indem Dinge geändert werden, die nicht geändert werden sollten. const teilt dem Compiler mit, dass Sie nicht zulassen möchten, dass diese Variable geändert wird, und der Compiler wird dies erzwingen.

  • Mit „der Compiler wird es erzwingen“ meinen Sie vermutlich, dass Sie erwarten, dass der Compiler eine Diagnose ausgibt, wenn der Quellcode versucht, ein Objekt durch einen konstant qualifizierten Typ zu ändern, nicht dass der Compiler Sie daran hindert, einen konstant qualifizierten Typ zu konvertieren Typ (oder Zeiger auf einen solchen) auf einen nicht konstant qualifizierten Typ (oder Zeiger auf einen solchen) und das Objekt durch den nicht konstanten Typ zu ändern, vorausgesetzt, dass eine solche Änderung vom C++-Standard erlaubt ist (was in einigen Situationen der Fall ist)?

    – Eric Postpischil

    5. August 2013 um 13:30 Uhr

Benutzer-Avatar
Xaqq

Nein, das müssen sie nicht. const Kompilierzeit ist und dem Compiler erlaubt, eine Art von Optimierung durchzuführen. Es ist jedoch nicht zwingend erforderlich, dass eine Variable an einer Nur-Lese-Speicherstelle abgelegt wird.

Siehe dieses Beispiel, das ist Undefiniertes Verhalten (Danke an Dyp für den Hinweis):

#include <iostream>

int     main()
{
  const int bla = 42;
  int       *ptr = const_cast<int *>(&bla);

  std::cout << *ptr << std::endl;
  *ptr = 21;
  std::cout << *ptr << std::endl;
}

Es wird ausgegeben 42 und 21aber es könnte auch abstürzen.

Sehen Sie sich jetzt dieses an:

#include <iostream>

int     main()
{
  const int bla = 42;
  int       *ptr = const_cast<int *>(&bla);

  std::cout << bla << std::endl;
  *ptr = 21;
  std::cout << bla << std::endl;
}

Auf meinem Compiler diese Ausgabe 42 und 42, weil der Compiler einige Optimierungen vorgenommen hat. Beachten Sie, dass es immer noch abstürzen kann *ptr = 21;

  • *ptr = 21; Undefiniertes Verhalten.

    – dyp

    5. August 2013 um 12:28 Uhr


  • @DyP Bearbeitet. Könnten Sie mir Erklärungen oder Links zur Erklärung geben? *ptr = 21 ist UB? Ist nicht const_cast ein gültiges Konstrukt, das die Änderung der Variablen ermöglichen würde?

    – Xaqq

    5. August 2013 um 12:30 Uhr

  • Damit können Sie eine Variable ändern wenn diese Variable nicht deklariert wurde const. Ansonsten UB: [dcl.type.cv]/4 “Außer, dass irgendein Klassenmitglied deklariert hat mutable geändert werden kann, jeder Versuch, a const Objekt während seiner Lebensdauer führt zu undefiniertem Verhalten.”

    – dyp

    5. August 2013 um 12:31 Uhr


  • @DyP Ja, ich habe über String-Literal nachgedacht, dachte aber, sie wären eine Ausnahme. Lassen Sie mich bearbeiten, und vielen Dank für den Hinweis. Heute was gelernt 🙂

    – Xaqq

    5. August 2013 um 12:38 Uhr

  • Der Grund, warum Ihr Programm keinen Unterschied für den Speicherort / kein seltsames Verhalten für zeigt *ptr = 21; liegt wohl daran bla wird entweder auf dem Stack oder in einem Register auf einer x86-Architektur platziert; beide sind nicht schreibgeschützt.

    – dyp

    5. August 2013 um 12:41 Uhr


Benutzer-Avatar
Matt Petersson

Es gibt viele Fälle, in denen es dem Compiler nicht möglich ist, eine const in den Nur-Lese-Speicher (vorausgesetzt, es gibt überhaupt einen Nur-Lese-Speicher im System). Tatsächlich glaube ich, dass fast alle Compiler in der Regel make const Objekte leben im regulären Daten- (oder Stack-) Speicher, genau wie gewöhnliche Variablen.

Der Hauptzweck von const ist, dem Compiler gegenüber zu erklären, dass Sie einen Wert nicht ändern wollen und sollen. Ich sehe keinen Grund, warum Compiler unter bestimmten Umständen nicht put const Variablen im Nur-Lese-Speicher. Aber darauf würde ich mich auch nicht verlassen – der Standard macht das sicher möglich, da er die Verwendung erwähnt const_cast Löschen const von einem ursprünglich markierten Objekt constund dann darauf zu schreiben, ist ein undefiniertes Verhalten (der Compiler muss also nicht zulassen, dass der Wert nach der Verwendung geändert wird const_cast um das Original zu entfernen const – und ermöglicht daher “Absturz, weil wir versucht haben, in den Nur-Lese-Speicher zu schreiben”).

Aber bedenke Folgendes:

class X
{
   int x;
  public:
   X(int v) : x(v) {}
}

int c = rand();

const X a(c+1);
const X b(c+2); 

In diesem Fall kann der Compiler den Wert in nicht kennen c von dem es kam randkann also nicht initialisiert werden a und b zur Kompilierzeit.

  • Entschuldigung, ich meinte, an a zu schreiben const Objekt, das hatte const ENTFERNT. Ich habe geklärt, was ich ausstrahle.

    – Mats Petersson

    5. August 2013 um 12:56 Uhr

  • Okay 🙂 aber ich könnte immer noch pedantisch sein: char c; char const& rc = c; -> rc ist ebenfalls eine Variable und wird deklariert const.

    – dyp

    5. August 2013 um 12:58 Uhr

  • Ich bin mir nicht sicher, ob ich Ihren Pedantismus verstehe. rc ist ein const Bezug auf calso dieselbe Variable wie c – in diesem Fall ist es gültig bis const_cast Weise die Konstante und schreiben Sie in die Referenz, wodurch der ursprüngliche Wert von geändert wird c.

    – Mats Petersson

    5. August 2013 um 13:02 Uhr

  • In der Tat, aber es könnte so interpretiert werden entfernen const aus einer Variablen [rc] das war ursprünglich markiert const. Der Standard verwendet seine eigene Terminologie und spricht von const Objekte anstelle von Variablen (oder Variablendeklarationen). Ein anderes Beispiel: new const int{5}; (ein Objekt, aber ich würde es nicht als Variable betrachten)

    – dyp

    5. August 2013 um 13:05 Uhr


Das const Schlüsselwort hat zwei Verwendungen:

  1. Das bekannte „Ich verspreche, den Zustand dieses Objekts nicht zu ändern“
  2. Als Sonderregel der Compiler kann Objekte platzieren, deren Definition ist const im Nur-Lese-Speicher, solange das Objekt keine hat mutable Mitglieder (dh das gesamte Objekt ist der Zustand des Objekts).

Deswegen const_cast Es ist erlaubt, den const-Qualifizierer zu entfernen, aber eine Voraussetzung ist, dass die Objektdefinition selbst dies nicht ist const. Wikipedia zur konstanten Korrektheit besagt, dass “Jeder Versuch, ein Objekt zu ändern, das selbst als const deklariert ist, mittels const_cast zu einem undefinierten Verhalten gemäß dem ISO-C++-Standard führt.”.

Das garantiert nicht nur der C++-Standard nicht const Objekte im Nur-Lese-Speicher befinden, wäre es für eine Implementierung schwierig, sie vollständig zu implementieren, wie unten erläutert wird.

Es wäre schwierig, eine C++-Implementierung zu platzieren const Objekte mit automatischer Speicherdauer, deren Adressen in den Festwertspeicher übernommen werden. Dies liegt daran, dass jedes unterschiedliche Objekt eine unterschiedliche Adresse haben muss (weil ihre Zeiger ungleich sein müssen). Jedes solche Objekt muss also jedes Mal erstellt werden, wenn der Block, in dem es sich befindet, ausgeführt wird.

Wenn ein const Da die Adresse des Objekts nicht verwendet wird, kann der Compiler die mehreren Instanzen davon (im C++-Rechenmodell) mit nur einer einzigen Instanz im Speicher implementieren (da jede Instanz identisch ist und sich nicht ändert). So kann ein solches Objekt einmal beim Programmstart erstellt werden (wahrscheinlich durch Laden aus einem Abschnitt mit konstanten Daten der Programmdatei), als schreibgeschützt markiert und für die Dauer der Programmausführung unverändert gelassen werden. Wenn jedoch die Adresse eines Objekts genommen (und auf beobachtbare Weise verwendet) wird, muss der Compiler jede einzelne Instanz des Objekts erstellen (oder irgendwie „vortäuschen“, dass eine Instanz mehrere Adressen hat). Im Allgemeinen kann ein Compiler nicht vorhersagen, wie viele Ausführungen eines Blocks gleichzeitig existieren können (z. B. wenn es rekursive Funktionsaufrufe gibt). Daher kann es beim Programmstart nicht alle Instanzen eines Objekts erzeugen, die benötigt werden. Sie müssen spontan erstellt werden.

Das Erstellen von Objekten erfordert das Ändern des Speichers, um die Anfangswerte der Objekte zu schreiben. Daher setzen const Objekte mit automatischer Speicherdauer im Nur-Lese-Speicher würden ein häufiges Ändern des Speichers von Nur-Lesen zu Beschreibbar und zurück erfordern. Um ein neues Objekt zu erstellen, müsste das Programm den Nur-Lese-Speicher in einen beschreibbaren Speicher ändern, den Anfangswert eines neuen Objekts schreiben und den Speicher wieder in einen Nur-Lese-Speicher ändern.

Darüber hinaus würde dies nur für Single-Thread-Programme ohne Signalhandler den Anschein eines Nur-Lese-Speichers erwecken. Programme mit mehreren Ausführungsthreads oder einzelnen Handlern können möglicherweise den Speicher beobachten, während er sich im beschreibbaren Zustand befindet.

Benutzer-Avatar
Cory Nelson

Was den Standard betrifft, gibt es keine Anforderung zu platzieren const Variablen in schreibgeschütztes RAM. const ist im Grunde nur eine vom Compiler erzwungene Dokumentation.

Wenn ein Wert vollständig zur Kompilierzeit berechnet werden kann, verwenden Compiler in der Regel einen Nur-Lese-Speicher für a const Variable. Andernfalls werden sie in die gleichen Read-Write-Heaps oder -Stacks wie alles andere platziert.

Benutzer-Avatar
john.dennis

Nein. Betrachten Sie a const Objekt mit a mutable Mitglied. Wie bereits erwähnt, ist const ein Kompilierzeitkonstrukt, das dem Programmierer dabei hilft, die Absicht zu vermitteln.

1283630cookie-checkWerden konstante Variablen im Nur-Lese-Speicher abgelegt? [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy