Wie ist der Nur-Lese-Speicher in C implementiert?

Lesezeit: 6 Minuten

Ich habe das in C gehört, wenn ich das tue

char *s = "hello world". 

das “Hallo Welt” ist tatsächlich im Nur-Lese-Speicher gespeichert.

Ich bin nicht so klar über den Nur-Lese-Speicher. Was ist die Erklärung? Ist das wie ein Flag für den Compiler, das den Compiler anweist, nicht in diesen Abschnitt zu schreiben?

  • Haben Sie eine Referenz? Ich denke, du meinst vielleicht: const char* s = “hello world”.

    – Jakob Schwarz

    10. November 2009 um 0:29 Uhr

  • Es ist nicht klar, dass alle Prozessorarchitekturen geschützten Speicher unterstützen.

    – Jldupont

    10. November 2009 um 0:30 Uhr

  • @James Black: Das OP spricht offensichtlich über das Zeichenfolgenliteral "hello world"die tatsächlich im Nur-Lese-Speicher gespeichert werden können, unabhängig davon, wie der Zeiger deklariert ist.

    – AnT steht zu Russland

    10. November 2009 um 0:36 Uhr

  • meine Referenz ist: stackoverflow.com/questions/1704407/…

    Benutzer188276

    10. November 2009 um 0:40 Uhr

  • Ich bin auch neugierig, wenn wir eine Konstante deklarieren, z. B.: const int a; wird a auch in den Nur-Lese-Speicherbereich zugewiesen? (weil es konstant ist, nicht änderbar, also gehe ich davon aus)

    Benutzer188276

    10. November 2009 um 0:41 Uhr

Benutzer-Avatar
Nils Pipenbrink

Das ist kein Merkmal des C Sprache sondern eine Funktion des Compilers/Linkers und des Betriebssystems, die zusammenarbeiten.

Wenn Sie solchen Code kompilieren, passiert Folgendes:

  • Der Compiler fügt die Zeichenfolge in einen schreibgeschützten Datenabschnitt ein.

  • Der Linker sammelt alle Daten in solchen schreibgeschützten Abschnitten und fügt sie in ein einzelnes Segment ein. Dieses Segment befindet sich in der ausführbaren Datei und ist mit einem “nur lesen”-Attribut gekennzeichnet.

  • Jetzt kommt der ausführbare Loader des Betriebssystems. Es lädt die ausführbare Datei (oder bildet sie in den Speicher ab, um genauer zu sein). Sobald dies erledigt ist, geht der Lader die Abschnitte ab und legt Zugriffsberechtigungen für jedes Segment fest. Für ein schreibgeschütztes Datensegment wird höchstwahrscheinlich die Codeausführung und der Schreibzugriff deaktiviert. Code (z. B. Ihre Funktionen) erhält Ausführungsrechte, aber keinen Schreibzugriff. Gewöhnliche Daten wie statische Variablen erhalten Lese- und Schreibzugriff und so weiter …

So machen es moderne Betriebssysteme.

Wie gesagt, es ist kein Feature der C-Sprache. Kompiliert man das gleiche Problem zB für DOS, läuft zwar das Programm, aber es wäre kein Schreibschutz möglich, weil der DOS-Loader keine Read-Only-Sections kennt.

  • Setzt die konstante Variable auch den gleichen Abschnitt wie “Hallo Welt”? ( Bsp.: const int a = 6 )

    Benutzer188276

    10. November 2009 um 1:12 Uhr

  • “Es hängt davon ab, ob”. Das einzige, was Sie mit Sicherheit über eine Konstante int sagen können, ist, dass der Compiler eine Diagnosemeldung erzeugt, wenn Sie versuchen, sie zu ändern. Es kann in einem schreibgeschützten Abschnitt gespeichert werden, oder es wird möglicherweise überhaupt nie gespeichert und direkt als Konstante in die Anweisungen codiert, die es verwenden.

    – Markus Bessey

    10. November 2009 um 1:21 Uhr

  • @tsubasa – wahrscheinlich nicht und schon gar nicht wenn a ist ein Einheimischer. Aber was auch immer die Antwort ist, es hängt auch vom Betriebssystem und dem Ladeprogramm ab.

    – Stefan C

    10. November 2009 um 1:24 Uhr

  • Denken Sie auch daran, dass die Konstante sogar und höher in einem ROM sein kann. (Im Falle eines eingebetteten Programms.)

    – Prof. Falken

    10. November 2009 um 9:31 Uhr

  • @Nils Pipenbrinck Gibt es eine Möglichkeit, einen Compiler zu erzwingen, um das gesamte Programm einzufügen beschreibbar Erinnerung?

    – phimuemue

    28. Juli 2011 um 17:27 Uhr

Ausführbare Dateien bestehen aus zwei Teilen: einem .data-Abschnitt, der globale Variablen enthält, und einem .text-Abschnitt, der den eigentlichen Maschinencode enthält.

Zeichenfolgen werden in den .data-Abschnitt gestellt. Was C tut, wenn es „Hello world“ sieht, ist, dass es die Zeichenfolge „Hello world“ in die ausführbare Datei selbst einfügt und die Instanz von „Hello world“ im Programm durch die Adresse ersetzt, an der diese Zeichenfolge geladen wird.

Allerdings bin ich mir nicht sicher, warum es schreibgeschützt ist – theoretisch sollte ein Programm in der Lage sein, seinen eigenen Speicher zu ändern.

  • Nicht alle Prozessoren und Betriebssysteme unterstützen selbstmodifizierenden Code. Tatsächlich enthalten die meisten modernen Betriebssysteme als Sicherheitsfunktion einen Schutz vor selbstmodifizierendem Code.

    – Absturz

    10. November 2009 um 0:50 Uhr

  • String-Literale können und werden häufig im Textabschnitt gespeichert, da sie nicht modifizierbar sein müssen.

    – Café

    10. November 2009 um 1:09 Uhr

Echter Nur-Lese-Speicher wird durch das Speichersubsystem des Betriebssystems implementiert. Das Betriebssystem kann bestimmte Seiten als schreibgeschützt markieren.

In der Binärdatei kann der Compiler dem Betriebssystem mitteilen, welche Teile der ausführbaren Datei in Nur-Lese- oder Lese-Schreib-Speicherseiten platziert werden sollen.

  • hmmm … echter Speicherschutz wird auf Prozessorebene implementiert.

    – Jldupont

    10. November 2009 um 0:33 Uhr

  • @jldupont: Der Speicherschutz ist zwar auf Hardwareebene implementiert (zumindest in x86), aber die Ersteinrichtung erfolgt durch das Betriebssystem, dh es ist das Betriebssystem markiert Nur-Lese-Seiten als solche, und dann erzwingt die Hardware die vom Betriebssystem eingerichteten Nur-Lese-Markierungen.

    – AnT steht zu Russland

    10. November 2009 um 0:43 Uhr

  • @AndreyT: natürlich … mein Punkt war in Bezug auf @R Samuel. Ohne Hardware- Unterstützung, es gibt so viel, was man auf der Softwareebene tun kann.

    – Jldupont

    10. November 2009 um 0:50 Uhr

  • @R – Tatsächlich kann auf eingebetteten Systemen der Nur-Lese-Speicher tatsächlich mit ROM-Hardware implementiert werden. zB mit EPROM-Chips.

    – Stefan C

    10. November 2009 um 1:28 Uhr

Benutzer-Avatar
sneha maganahalli

Wenn du schreibst char s[10]="sneha"; Sie weisen Ihrer Objektdatei 10 Byte Speicherplatz zu (kein Speicher, Speicher kommt nur ins Bild, wenn Sie Ihr Programm ausführen). Dies ist eine statische Speicherzuweisung (zur Kompilierzeit).

Aber wenn du schreibst char *s="sneha"; Sie weisen keinen Speicherplatz zum Speichern zu "sneha". Es wird im Abschnitt NUR LESEN gespeichert. Aber der Zeiger s wird in einem anderen Abschnitt gespeichert, je nachdem, wo es deklariert ist. Aber es zeigt auf die READ ONLY DATA "sneha". Wenn Sie also versuchen, darauf zu schreiben, erhalten Sie einen Segmentierungsfehler.

Zum Beispiel:

char *s = "sneha";
s[1] = 'N'; 
printf("%s",s);  // you expecting output sNeha, 
                 // but you get a seg fault since it is READ ONLY DATA 

Benutzer-Avatar
Andreas Koch

Ein Beispiel dafür, wie dies unter Linux zu tun ist, finden Sie auf Seite 179 von Fortgeschrittene Linux-Programmierung von Mark Mitchell, Jeffrey Olham und Alex Samuel.

Benutzer-Avatar
Jared Updike

Du könntest so etwas versuchen

s[4] = '0';

und schau, ob es “hello w0rld” sagt, wenn du anrufst

puts(s);

Wenn es einen sofortigen Segmentierungsfehler oder eine Datenausführungsverhinderungs-Ausnahme verursacht, ist es wahrscheinlich schreibgeschützt. (Wenn das System Sie damit durchkommen lässt, ist es keine gute Idee.)

Benutzer-Avatar
Markus Bessey

Wie andere Leute bereits erwähnt haben, wird durch das Betriebssystem, den Compiler und die Chiparchitektur bestimmt, ob der Inhalt konstanter Zeichenfolgen im Nur-Lese-Speicher gespeichert wird.

Genauer gesagt legt der C-Standard fest, dass die Zeichenfolgen in Anführungszeichen “const char” haben[]” schreiben (oder entsprechende Worte, ich habe den Standard nicht zur Hand).

Jeder Code, der versucht, den Inhalt einer solchen Zeichenfolge zu ändern, ruft ein undefiniertes Verhalten auf. Das bedeutet, dass an diesem Punkt buchstäblich alles passieren kann, und der Anbieter des Compilers muss nicht einmal dokumentieren, was passieren kann.

In der Praxis bedeutet dies, dass ein C- oder C++-Programm, das portierbar sein möchte, vermeiden muss, konstante Zeichenfolgen zu ändern.

Im Allgemeinen erlaubt Ihnen der Compiler nicht, den Inhalt von “const”-Variablen zu ändern, daher können Sie “const” in den meisten Fällen als “schreibgeschützt” betrachten. Leider gibt es eine spezielle Ausnahme für char * und const char *, hauptsächlich aus historischen Gründen. Das bedeutet, dass Code so lautet:

char *x = "Hello, World";
*x = 'h';

wird ohne Fehler oder Warnung kompiliert, obwohl es undefiniertes Verhalten aufruft.

1369180cookie-checkWie ist der Nur-Lese-Speicher in C implementiert?

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

Privacy policy