2016-07-22 9 views
-2

In seiner einfachsten Form ist das ProgrammWarum verursacht dieses C-Programm keinen Segmentierungsfehler mit alphanumerischen Werten?

int main(){ 
    int x; 
    scanf("%d",x); 
} 

Wenn wir dieses Programm einen beliebigen numerischen Wert geben als Eingabe durch Erzeugen eines segfault Signal aus, das, was wir erwarten sollten, ist.

Wenn wir aber stattdessen einen alphanumerischen Wert angeben, schlägt nicht fehl.

Was passiert in der scanf, die dieses Verhalten erzeugt?

der Backtrace von GDB Dies wird, wenn es mit einem numerischen Wert ausgeführt wird:

(gdb) bt 

#0 0x00000034e7456ed0 in _IO_vfscanf_internal() from /lib64/libc.so.6 

#1 0x00000034e74646cd in __isoc99_scanf() from /lib64/libc.so.6 

#2 0x0000000000400553 in main() 

Warum ist es nicht wie ‚a‘ für jeden alphanumerischen Wert ausfällt oder ‚dfgb‘?

+4

Sie versuchen hier über * undefined Verhalten * nachzudenken. In diesem speziellen Fall könnte es sein, dass "scanf" nicht einmal versucht, auf das zweite Argument zuzugreifen, da die Eingabe nicht mit der Formatzeichenfolge übereinstimmt. Aber ich würde mich nicht darauf verlassen. –

+4

"Wenn ein Zeichen im Eingabestream mit format-string kollidiert, endet die Funktion und endet mit einem 'übereinstimmenden' Fehler. Das widersprüchliche Zeichen verbleibt im Eingabestream so, als wäre es nicht gelesen worden." Ihre alphabetischen Eingaben stimmen nicht mit dem erwarteten Dezimalformat überein, so dass 'scanf()' beendet wird, ohne zu versuchen, etwas an Ihre fehlerhafte "Adresse" zu schreiben. –

+0

Nicht einverstanden mit "Wenn wir diesem Programm irgendeinen numerischen Wert als Eingabe geben, schlägt es fehl, indem ein Segfault-Signal erzeugt wird, was wir erwarten sollten." Bei diesem Code führt die Eingabe von Zahlen zu einem undefinierten Verhalten, nicht unbedingt zu einer Segmentierung. Seg ist eine mögliche Erwartung, aber nicht die einzige. – chux

Antwort

5

Abschnitt 7.21.6.2/10 der Norm sagen:

Wenn das Eingabeelement nicht eine passende Sequenz ist, schlägt die Ausführung der Richtlinie: Diese Bedingung ist ein Anpassungsfehler.

und 7.21.6.2/4:

fscanf Die Funktion führt jede Anweisung des Formats der Reihe nach. Wenn alle Anweisungen ausgeführt wurden oder eine Direktive fehlschlägt (wie unten beschrieben), kehrt die Funktion zurück. Fehler werden als Eingabe Fehler (aufgrund des Auftretens eines Codierungsfehlers oder der Nichtverfügbarkeit von Eingabezeichen) oder Übereinstimmungsfehlern (aufgrund von ungeeigneter Eingabe) beschrieben.

Wie Sie Ihre Eingabe nicht gut parsable ganze Zahl liefert, scanf nur 0 zurück, um zu signalisieren, dass keine Umwandlung von Eingabe gemacht wurde, und versuchen Sie nicht zu dereferenzieren das Argument Sie übergeben.

Diese Antwort wurde editiert, um den Standard über diesen Punkt zu zitieren, danke an @Zwol.

+3

Ich glaube nicht, dass dies ein undefiniertes Verhalten ist. [N1570] (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) Abschnitt 7.21.6.2 ist die Spezifikation von (f) scanf.Das Verhalten von Konvertierungsdirektiven wird als Schritt-für-Schritt-Algorithmus beschrieben, und es scheint mir, dass die Implementierung ** nicht ** erforderlich ist, um auf das "Objekt" zuzugreifen, auf das das erste Argument folgt hat ein Konvertierungsergebnis erhalten, "es sei denn, die Konvertierung ist erfolgreich. Da dies eine variadische Funktion ist, erzwingt nichts anderes, dass jedes variable Argument ein Zeiger ist. – zwol

+0

@zwol Das ist richtig, 7.21.6.2/10 ist klar darüber, muss bearbeitet werden, danke. –

Verwandte Themen