Warum erhalte ich keinen Segmentierungsfehler, wenn ich über das Ende eines Arrays hinaus schreibe?

Lesezeit: 4 Minuten

Warum erhalte ich keinen Segmentierungsfehler wenn ich uber das Ende
singen

Warum gibt das beim Kompilieren keinen Fehler?

#include <iostream>
using namespace std;

int main()
{
    int *a = new int[2];
    // int a[2]; // even this is not giving error
    a[0] = 0;
    a[1] = 1;
    a[2] = 2;
    a[3] = 3;
    a[100] = 4;
    int b;

    return 0;
}

kann jemand erklären, warum dies geschieht. Vielen Dank im Voraus.)

  • Leider definiertes Verhalten manchmal ist eine Teilmenge von undefiniertem Verhalten 🙁

    – Mahesh

    13. September 2012 um 15:44 Uhr


  • @LuchianGrigore Manchmal

    – Mahesh

    13. September 2012 um 15:45 Uhr

  • @Mahesh nein … per Definition … erwartetes Verhalten ist eine Teilmenge von undefiniertem Verhalten. Aber UB und definiertes Verhalten sind disjunkt.

    – Luchian Grigore

    13. September 2012 um 15:46 Uhr

  • Versuchen Sie, die Speicherfreigabe hinzuzufügen [operator delete] und ich denke, du wirst deinen segfault nehmen. Betriebssystemüblich gibt Speicher nach fehlerfrei abgeschlossenen Prozessen frei. Und vergessen Sie nicht, die zweite On-Stack-Deklaration von “a” zu entfernen.

    – Pavel Ognew

    13. September 2012 um 15:49 Uhr

  • wechseln Sie den Compiler oder aktivieren Sie mehr Warnungen. die Doppeldefinition von a ist einfach nur schrecklich

    – Stefan

    13. September 2012 um 16:12 Uhr

Denn undefiniertes Verhalten == alles kann passieren. Sie haben Pech, dass es nicht abstürzt, diese Art von Verhalten kann möglicherweise Fehler verbergen.

Wie für a doppelt definiert werden – das ist ein Fehler im Compiler.

  • Es tut mir leid. “a” wurde nicht zweimal deklariert. Ich wollte nur sagen, dass sich beide Deklarationen ähnlich verhalten.

    – Singsingh

    14. September 2012 um 6:19 Uhr

  • @singingsingh ok 🙂 dann ignoriere den zweiten Absatz.

    – Luchian Grigore

    14. September 2012 um 7:14 Uhr

Warum erhalte ich keinen Segmentierungsfehler wenn ich uber das Ende
Mike Seymour

Deklarieren von zwei Variablen aufgerufen a ist sicherlich ein Irrtum; Wenn Ihr Compiler das akzeptiert, dann ist es kaputt. Ich nehme an, Sie meinen, dass Sie immer noch keinen Fehler erhalten, wenn Sie eine Deklaration durch die andere ersetzen.

Der Array-Zugriff ist nicht bereichsgeprüft. Zur Kompilierzeit ist die Größe eines Arrays oft nicht bekannt, und die Sprache erfordert keine Überprüfung, selbst wenn dies der Fall ist. Zur Laufzeit würde eine Überprüfung die Leistung beeinträchtigen, was gegen die C++-Philosophie verstoßen würde, nicht für etwas zu bezahlen, das Sie nicht benötigen. Der Zugriff über das Ende eines Arrays hinaus führt also zu undefiniertem Verhalten, und es liegt am Programmierer, dafür zu sorgen, dass dies nicht geschieht.

Manchmal verursacht ein ungültiger Zugriff einen Segmentierungsfehler, aber dies ist nicht garantiert. Typischerweise wird der Speicherschutz nur auf ganze Speicherseiten angewendet, mit einer typischen Seitengröße von einigen Kilobyte. Jeder Zugriff innerhalb einer Seite mit gültigem Speicher wird nicht abgefangen. Es besteht eine gute Chance, dass der Speicher, auf den Sie zugreifen, eine andere Programmvariable oder einen Teil des Aufrufstapels enthält, sodass das Schreiben dort das Verhalten des Programms auf nahezu jede erdenkliche Weise beeinflussen könnte.

Wenn Sie sicher sein wollen, können Sie verwenden std::vectorund greifen Sie nur mit its auf seine Elemente zu at() Funktion. Dadurch wird der Index überprüft und eine Ausnahme ausgelöst, wenn er außerhalb des zulässigen Bereichs liegt. Es verwaltet auch die Speicherzuweisung für Sie und behebt das Speicherleck in Ihrem Beispiel.

  • Es tut mir leid. “a” wurde nicht zweimal deklariert. Ich wollte nur sagen, dass sich beide Deklarationen ähnlich verhalten.

    – Singsingh

    14. September 2012 um 6:19 Uhr

1647121214 606 Warum erhalte ich keinen Segmentierungsfehler wenn ich uber das Ende
oops

Ich vermute, Sie kommen aus Java oder einer Java-ähnlichen Sprache, wo Sie die Ausnahme “Array-Index außerhalb der Grenzen” erhalten, sobald Sie die Grenze eines Arrays verlassen.

Nun, C erwartet mehr von Ihnen; Es spart den von Ihnen angeforderten Speicherplatz ein, überprüft jedoch nicht, ob Sie die Grenze dieses eingesparten Speicherplatzes überschreiten. Sobald Sie dies wie oben erwähnt tun, zeigt das Programm dieses gefürchtete undefinierte Verhalten.

Und denken Sie für die Zukunft daran, dass, wenn Sie einen Fehler in Ihrem Programm haben und ihn anscheinend nicht finden können, und wenn Sie den Code durchgehen/debuggen, alles in Ordnung zu sein scheint, besteht eine gute Chance, dass Sie “aus sind Grenzen” und Zugriff auf einen nicht zugeordneten Ort.

Compiler mit guter Codeanalyse würden sicherlich vor diesem Code warnen, der über Ihre Arrayzuweisung hinaus verweist. Wenn Sie die mehrfache Deklaration vergessen, wenn Sie sie ausgeführt haben, kann sie fehlerhaft sein oder nicht (undefiniertes Verhalten, wie andere gesagt haben). Wenn Sie beispielsweise eine 4-KB-Heap-Seite (im Adressraum des Prozessors) haben und nicht außerhalb dieser Seite schreiben, erhalten Sie keinen Fehler vom Prozessor. Beim Löschen des Arrays, falls Sie dies getan haben, und abhängig von der Heap-Implementierung, erkennt der Heap möglicherweise, dass er beschädigt ist.

995260cookie-checkWarum erhalte ich keinen Segmentierungsfehler, wenn ich über das Ende eines Arrays hinaus schreibe?

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

Privacy policy