2016-07-20 18 views
0

Ich habe einen Code wie unten:Gewährleistet Const Struct Pointer Sicherheit vor Speicherbeschädigung/Absturzproblemen?

struct abc 
{ 
    int *xyz; 
} 

void func1(abc *ptr, .... lots of other struct ptrs passed) 
{ 
    func2(ptr->xyz) // some computation, only read from ptr->xyz 
    ... 
    ... 
    func3(ptr->xyz) // some computation, ptr->xyz is only read 
} 

void main() 
{ 
    abc *ptr; 
    // memory is allocated properly here for ptr and ptr->xyz. 
    func1(ptr,...); 
} 

Problem: Seg Fehler passiert bei func3, ptr- aufgrund> xyz = 0x0. Bis func2, ptr-> xyz Adresse ist richtig. und keinen anderen verwandten Code vor func3. Nicht reproduzierbar. Nicht viele Informationen von Core-Dump in Bezug auf den Beginn der Speicherbeschädigung oder Valgrind.

Analyse: Ich lief GDB und verwendete Befehl awatch * (Adresse von ptr-> xyz) für den normalen Arbeitsfall. Überall Func1, Func2, Func3, lesen wir nur von ptr-> xyz Speicheradresse. Im normalen Arbeitsszenario findet keine Schreiboperation statt. Also ich glaube, dass dies aufgrund einer anderen Speicherbeschädigungsüberlappung sein könnte.

Frage: Wenn ich als void func1 übergeben (const abc * const ptr). Ich möchte Adresse/Daten von abc oder abc-> xyz nicht ändern. Stellt "const" sicher, dass struct abc, abc-> xyz immer in einem schreibgeschützten Segment im Speicher gespeichert wird und somit vor Speicherkorruption geschützt ist? vielleicht wegen anderer struct memory address overlap schreiben?

Danke!

Antwort

4

Stellt "const" sicher, dass struct abc, abc-> xyz immer in einem schreibgeschützten Segment im Speicher gespeichert wird und daher vor Speicherkorruption geschützt ist?

Nein, nicht immer. Mit const werden Diagnosen (Warnungen/Fehler) zur Kompilierzeit ausgegeben, wenn der Code wissentlich versucht, die Variable zu modifizieren.

Wenn versucht wird, ein mit einem Konst-qualifizierten Typ definiertes Objekt mithilfe eines Lvalue mit einem nicht konformen Typ zu ändern, ist das Verhalten nicht definiert. C11 §6.7.3 6

Sollte Versuch, zur Laufzeit, codiert eine const Variable zu ändern, es könnte funktionieren, es unbemerkt fehlschlagen kann, kann es das Programm zum Absturz bringen. Es ist undefiniertes Verhalten.

In OP-Fall, verdächtigen Code schreibt außerhalb Grenzen und in Feld xyz, so xyzconst wird nicht viel helfen.

+1

Sie könnten den Unterschied zwischen einem * const-Objekt *, das an seinem Definitionspunkt initialisiert wird, und einem Zeiger auf const * function-Parameter * hervorheben. Das * const-Objekt * kann sich physikalisch in einem Nur-Lese-Speicher befinden. Der * Zeiger * zeigt auf ein existierendes Objekt, das selbst const sein kann oder nicht. Die Angabe des Zeigers auf die eine oder andere Weise ist nur ein Hinweis auf die Absicht (und beeinflusst die Überladungsauflösung). Es ändert in keiner Weise den Charakter des Speichers, auf den gezeigt wird. –

+0

@Peter A. Schneider 1) Ja, "Das const-Objekt kann sich physikalisch in einem Nur-Lese-Speicher befinden.", Weiß OP sicherlich. OP möchte wissen, ob das immer stimmt - das ist es nicht. 2) Unklar auf "beeinflusst die Überladungsauflösung" auf diesem C-Post. Vielleicht sind Sie eine andere Sprache? "const" hat eine subtilere Bedeutung in C als andere Sprachen. Es ist eher "schreibgeschützt" als "konstant". – chux

+0

(1) Oh. C. Ja, keine Überladungsauflösung. "(2) OP weiß das sicher": Ich hatte die Ahnung, dass er ein Speicherüberschreiben verhindern wollte, indem er den * Zeiger * auf ein konstantes Objekt zeigte, ohne die Objektdefinition zu ändern (beachten Sie die "Wenn ich als void func1 (const abc * const ptr) aus dem Post übergeben". Das würde natürlich nichts tun. –