2011-01-13 9 views
0

Ich habe zwei Fragen Array in Bezug auf:segfault mit Array

erste ist über folgenden Code:

int a[30]; //1 
a[40]=1; //2 

warum ist nicht die Linie 2 geben segfault, sollte es geben, weil Array zugeteilt wurde nur 30 int-Platz und jede Dereferenzierung außerhalb ihres zugewiesenen Speicherplatzes sollte segfault ergeben.

Zweitens: angenommen, dass der obige Code funktioniert, gibt es eine Chance, dass a [40] über geschrieben wird, da es nicht der reservierte Bereich von arrray ist.

Vielen Dank im Voraus.

+0

Verschlagwortet mit C, werden nicht viele Sprachen still dies schlucken. – leppie

Antwort

4

Das ist undefiniertes Verhalten - es kann zum Absturz kommen, es kann Daten unbemerkt verfälschen, es kann keine beobachtbaren Ergebnisse, irgendetwas produzieren. Tu es nicht.

In Ihrem Beispiel ist die wahrscheinlichste Erklärung, dass das Array stack-allocated ist und somit eine breite Palette von Adressen rund um das Array zum Schreiben verfügbar ist, so dass es keine sofort beobachtbaren Ergebnisse gibt. Je nachdem, wie (zu welcher Richtung - zu größeren Adressen oder zu kleineren Adressen) der Stack auf Ihrem System wächst, überschreibt dies möglicherweise die Rücksprungadresse und Provisorien von Funktionen des Aufruf-Stacks, was Ihr Programm zum Absturz bringt oder es falsch macht Rückkehr von der Funktion.

+4

Es könnte sogar Ihre Freundin schwanger bekommen, egal ob Sie eine haben oder nicht! – fredoverflow

1

Aus Leistungsgründen wird C die Array-Größe nicht bei jedem Zugriff überprüfen. Sie können auch über direkte Zeiger auf Elemente zugreifen. In diesem Fall besteht keine Möglichkeit, den Zugriff zu validieren. SEGFAULT tritt nur dann auf, wenn Sie keinen Speicher mehr für Ihren Prozess haben.

Für die zweite Frage, ja kann es überschrieben werden, da dieser Speicher Ihrem Prozess zugeordnet ist und möglicherweise von anderen Variablen verwendet wird.

1

Es hängt davon ab, wo das System dieses Array zugewiesen hat, wenn die Position 40 in einem reservierten Arbeitsspeicher des Betriebssystems ist, dann erhalten Sie segfault.

0

Ja, es wird eventuell überschrieben.

Wenn Sie malloc Speicherplatz, sollten Sie einen segfault (oder zumindest glaube ich), aber wenn Sie ein Array ohne Zuweisung von Speicherplatz verwenden, können Sie Speicher für eine Weile überschreiben. Es wird schließlich abstürzen, möglicherweise, wenn das Programm eine Überprüfung der Array-Größe oder vielleicht, wenn Sie einen Speicherblock für etwas anderes reserviert treffen (nicht sicher, was unter der Haube passiert).

Lustige Sache ist, dass IIRC, efence das auch nicht fangen wird: D.

+0

selbst mit malloc erhalten Sie möglicherweise keinen segfault, abhängig vom Betriebssystem und anderen Speicherzuweisungen, die vom Prozess ausgeführt werden. –

+0

Oh, das ist richtig, ich erinnere mich daran, dass es sich unter Windows und Linux anders verhält ... Nun, am besten vermeiden Sie das einfach: D. – mingos

1

Ihre Anwendung wird nur abstürzen, wenn Sie etwas illegal für den Rest Ihres Systems tun: Wenn Sie versuchen, auf eine virutale Speicheradresse zuzugreifen, die Ihr Programm nicht besitzt, was Ihre Hardware bemerken wird, informiert Ihr Betriebssystem, und es wird Ihre Anwendung mit einem Segmentierungsfehler beenden: Sie haben auf ein Speichersegment zugegriffen, das Sie nicht verwenden sollten.

Allerdings, wenn Sie Zugriff auf einen Zufalls Speicheradresse (das ist, was Sie getan haben: sicher a[40] außerhalb des Arrays ist a, aber es könnte überall sein), können Sie eine gültige Speicherzelle zugreifen konnte (was passiert ist für dich).

Dies ist ein Fehler: Sie überschreiben wahrscheinlich einen Speicherbereich, den Ihr Programm besitzt, und riskieren, Ihr Programm an anderer Stelle zu unterbrechen, aber das System kann nicht wissen, ob Sie es aus Versehen oder aus Versehen aufgerufen haben und Sie nicht töten.

Programme, die in verwalteten Sprachen geschrieben wurden (dh Programme, die in einer geschützten Umgebung laufen), würden Ihren fehlerhaften Speicherzugriff bemerken, aber C ist keine verwaltete Sprache: Sie können tun, was Sie wollen (sobald Sie schaffen keine Probleme für den Rest des Systems).

1

Der Grund, warum Zeile 2 funktioniert und keinen segfault auslöst, liegt darin, dass Arrays in C/C++ Zeiger sind. Ihre Array-Variable a zeigt also auf eine Speicheradresse, z. 1004. Die Array-Syntax teilt Ihrem Programm mit, wie viele Bytes von der Position von a entfernt sind, um nach einem Array-Element zu suchen.

Das bedeutet, dass

printf("%p", a); 
// prints out "1004" 

und

printf("%p", a[0]); 
// prints out "1004" 

sollte den gleichen Wert drucken.

jedoch

printf("%p", a[40]); 
// prints out "1164" 

liefert die Speicheradresse, die sizeof (int) * 40 nach unten von der Adresse von a ist.