2012-09-13 7 views
5

Warum gibt dies keinen Fehler, wenn ich kompiliere?Warum bekomme ich keinen Segmentierungsfehler, wenn ich über das Ende eines Arrays hinaus schreibe?

#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 das passiert. Vielen Dank im Voraus.)

+4

Leider ist das definierte Verhalten ** manchmal ** eine Untermenge von undefiniertem Verhalten :( – Mahesh

+0

@Mahesh :)) Nein. –

+1

@LuchianGrigore ** Manchmal ** – Mahesh

Antwort

2

Ich vermute, dass Sie aus Java oder einer Java-ähnlichen Sprache kommen, wo Sie die Ausnahme "array index out of bounds" erhalten, sobald Sie die Grenze eines Arrays verlassen haben.

Nun, C erwartet mehr von Ihnen; es spart den Raum, den Sie verlangen, aber es prüft nicht, ob Sie außerhalb der Grenzen dieses Speicherplatzes gehen. Sobald Sie das wie oben erwähnt tun, hat das Programm dieses gefürchtete undefinierte Verhalten.

Und erinnern Sie sich für die Zukunft, wenn Sie einen Fehler in Ihrem Programm haben und Sie nicht scheinen können, es zu finden, und wenn Sie über den Code gehen/debuggen, scheint alles in Ordnung, es besteht eine gute Chance, Sie ' re "out of bounds" und Zugriff auf einen nicht zugewiesenen Ort.

9

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

Wie für a wird zweimal definiert - das ist ein Fehler im Compiler.

+0

Es tut mir leid. "a" wurde nicht zweimal deklariert. Ich wollte nur sagen, dass sich beide Erklärungen ähnlich verhalten. – singingsingh

+0

@singingsingh ok :) dann ignorieren Sie den zweiten Absatz. –

8

Das Deklarieren von zwei Variablen namens a ist sicherlich ein Fehler; Wenn dein Compiler das akzeptiert, ist es kaputt. Ich nehme an, Sie meinen, dass Sie immer noch keinen Fehler erhalten, wenn Sie eine Erklärung durch die andere ersetzen.

Array-Zugriff wird nicht bereichsüberprüft. Zum Zeitpunkt der Kompilierung ist die Größe eines Arrays oft nicht bekannt, und die Sprache erfordert auch dann keine Überprüfung. Zur Laufzeit würde eine Überprüfung die Leistung beeinträchtigen, was gegen die C++ - Philosophie, nicht für etwas zu bezahlen, das Sie nicht benötigen, zu gehen. Ein Zugriff über das Ende eines Arrays hinaus gibt ein undefiniertes Verhalten, und es liegt am Programmierer, sicherzustellen, dass dies nicht geschieht.

Manchmal verursacht ein ungültiger Zugriff einen Segmentierungsfehler, aber dies ist nicht garantiert. In der Regel wird der Speicherschutz nur auf ganze Seiten des Speichers mit einer typischen Seitengröße von einigen Kilobyte angewendet. 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, so dass das Schreiben des Programms das Verhalten des Programms auf fast jede denkbare Weise beeinflussen kann.

Wenn Sie sicher sein möchten, können Sie std::vector verwenden und nur auf seine Elemente zugreifen, indem Sie die at()-Funktion verwenden. Dies überprüft den Index und löst eine Ausnahme aus, wenn er außerhalb des Bereichs liegt. Es verwaltet auch die Speicherzuweisung für Sie und behebt das Speicherleck in Ihrem Beispiel.

+0

Es tut mir leid. "a" wurde nicht zweimal deklariert. Ich wollte nur sagen, dass sich beide Erklärungen ähnlich verhalten. – singingsingh

0

Compiler mit guter Code-Analyse würde sicherlich auf diese Code-Referenzierung über Ihre Array-Zuweisung warnen. Vergessen Sie das Multiple einer Deklaration, wenn Sie es ausgeführt haben, kann es oder nicht Fehler (undefiniertes Verhalten, wie andere gesagt haben). Wenn Sie zum Beispiel eine 4-KByte-Seite des Heapspeichers (im Adressraum des Prozessors) haben, erhalten Sie keinen Fehler vom Prozessor, wenn Sie nicht außerhalb dieser Seite schreiben. Beim Löschen des Arrays, wenn Sie es getan haben, und abhängig von der Heap-Implementierung, könnte der Heap erkennen, dass er beschädigt ist.

Verwandte Themen