Frage

Wie viele junge Programmierer tun, habe ich gelernt, die Nützlichkeit zahlreiche einzufügen Print-to-Konsole Aussagen von „here1 Motiv“, „here2“, und so weiter an verschiedenen Stellen im Code, um herauszufinden, wenn meine Programme schief gehen. Diese Brute-Force-Debugging-Technik hat mich gerettet viele, viele Male in meinen CS-Studien. Allerdings, wenn ich die Programmierung in C begann, stieß ich auf ein interessantes Problem. Wenn ich versuche und läuft

void* test;

printf("hello world");
test[5] = 234;

Natürlich bekomme ich eine segfault für nicht-Speicher malloc'ing für testChar. Allerdings könnte man denken, logisch, dass „Hallo Welt“ würde gedruckt werden, bevor der seg Fehler geschieht, da, dass der Fluss des Codes ist, aber nach meiner Erfahrung ist es immer der Fall, dass die seg Fehler zuerst eintreten, und „Hallo Welt "ist überhaupt nicht auf die Konsole ausgegeben. (Ich war nicht in der Lage genau dieses Beispiel zu testen, aber ich habe in einem solchen Situation oft lief mit gcc auf einer Linux-Box.) Ich vermute, dies entweder mit dem Compiler zu tun hat einige Dinge neu anordnen und / oder printf indem eine Art Puffer, der asynchron und daher nicht sofort zu sein gespült wird. Dies ist völlig Spekulation meinerseits, weil ich ehrlich weiß nicht, warum es passiert. In einer anderen Sprache, die ich verwendet habe, egal, welches Problem der „testChar = ...“ Linie verursacht, die „Hallo Welt“ würde noch gedruckt werden, und so konnte ich feststellen, wo das Problem ist.

Meine Frage ist, warum dies passiert, wenn ich C bin Programmierung? Warum ist nicht die Hallo Welt zuerst gedruckt? Und zweitens gibt es eine bessere C-Programmierung Debug-Technik als diese, die die gleiche grundlegende Sache erfüllt? Wie in, eine einfache / intuitive Art und Weise die Codezeile zu finden, die ein Problem ist?

Edit: Ich habe ein funktionierendes Beispiel durch Zufall haha. Was ich habe, jetzt sollte eine segfault verursachen. Es ist schon komisch, wie in der Regel, wenn I nicht ein segfault ich einen bekommen will, und jetzt, wenn ich wollte eigentlich eine I Rechtskode!

schrieb
War es hilfreich?

Lösung

Der Code Sie auf dem Laufenden ist vollkommen legal und soll eine segfault nicht dazu führen - es gibt keine Notwendigkeit, etwas zu malloc. Ihr Problem muss woanders liegen -. Bitte das kleinste Beispiel für Code schreiben, die das Problem verursacht

Edit: Sie haben den Code nun bearbeitet eine ganz andere Bedeutung zu haben. Dennoch ist der Grund, dass „Hallo Welt“ nicht angezeigt wird, ist, dass die der Ausgangspuffer gespült worden ist. Versuchen Sie addinig

fflush( stdout );

nach der printf.

Bezüglich der Lokalisierung der Quelle des Problems Sie haben ein paar Möglichkeiten:

  • zügig bestreuen printfs durch den Code des __FILE__ und __LINE__ C-Makros mit
  • lernen, Ihren Debugger verwenden -. Wenn Ihre Plattform Core-Dumps unterstützt, können Sie das Core-Image verwenden, um herauszufinden, wo der Fehler

Andere Tipps

printf schreibt auf die Standardausgabe, die gepuffert wird. Manchmal ist dieser Puffer nicht geleert erhalten, bevor Ihr Programm stürzt so nie Sie die Ausgabe sehen. Zwei Möglichkeiten, um dies zu vermeiden:

  1. Verwendung fprintf( stderr, "error string" ); da stderr nicht gepuffert wird.
  2. fügen Sie einen Anruf nach dem printf Aufruf fflush( stdout );.

Wie Neil und andere gesagt haben, wie der Code geschrieben ist in Ordnung. Das heißt, bis starten Sie den Puffer zu modifizieren, die testChar Punkte.

„Wie in, eine einfache / intuitive Art und Weise die Codezeile zu finden, die ein Problem ist?“

Verwenden Sie gdb (oder ein anderer Debugger).

zu finden, wo Ihr Programm seg Fehler Sie es mit -g Option kompilieren (einschließlich Debugging-Symbole) führen Sie Ihre Anwendung von gdb , wird es auf seg Fehler zu stoppen.

Sie können dann bei Backtrace mit bt Befehl um zu sehen, an welcher Stelle Sie die seg Fehler bekam.

Beispiel:

> gdb ./x
(gdb) r
Starting program: /proj/cpp/arr/x 
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00000000
0x000019a9 in willfail () at main.cpp:22
22          *a = 3;
(gdb) bt
#0  0x000019a9 in willfail () at main.cpp:22
#1  0x00001e32 in main () at main.cpp:49
(gdb) 

Die Ausgabe standardmäßig gepuffert wird, tritt der segfault vor der Ausgabe auf stdout tatsächlich geschrieben wird. Versuchen Sie:

fprintf(stderr, "hello, world\n");

(stderr ist ungepufferte standardmäßig aktiviert.)

Dieser Code soll nicht segfault. Sie sind nur einen Zeiger auf eine Zeichenkette in einen Zeiger Variablen zugewiesen wird. Dinge wären anders, wenn Sie sind z.B. mit strcpy Material mit einem ungültigen Zeiger zu kopieren.

Die Nachricht nicht kann aufgrund gepufferte I / O erscheint. Drucken Sie ein Newline-Zeichen \n oder rufen fflush den Ausgabepuffer zu spülen.

Sie haben zwei Probleme. Die erste ist, dass Ihr (original) Code nicht segfault wird. Es ist durchaus möglich, dass die String-Konstante auf einen char Zeiger zuweisen. Aber lassen wir das beiseite für jetzt und so tun Sie etwas gelegt hatte es, dass würde segfault.

Dann ist es in der Regel eine Frage des Puffers, der in der C-Laufzeitbibliothek und die in dem O selbst. Sie müssen sie spülen.

Der einfachste Weg, das zu tun war (in UNIX, nicht ganz sicher über die fsync in Linux, aber Sie sollen garantiert werden, dass diese schließlich passieren wil es wäre denn, das System selbst nach unten geht):

printf ("DEBUG point 72\n"); fflush (stdout); fsync (fileno (stdout));

Ich habe dies oft in UNIX getan, und es ist sichergestellt, dass die C-Laufzeitbibliotheken zu UNIX gespült werden (fflush) und der UNIX-Puffer auf der Festplatte (fsync) ist sync'ed, nützlich, wenn stdout kein Endgerät ist oder Sie ‚re es für eine andere Datei-Handle zu tun.

void* test;

printf("hello world");
test[5] = 234;

Es ist wahrscheinlich, dass „Hallo Welt“ ist irgendwo durch das System gepuffert wird und nicht sofort auf dem Bildschirm ausgegeben. Sein für eine Chance gespeichert wartet auf was Prozess / Thread / was auch immer verantwortlich für Bildschirm schreiben ist eine Chance, es zu verarbeiten hat. Und während seiner Warte (und möglicherweise Pufferung andere Daten zur Ausgabe) Sie ist Funktion beenden. Es kommt über den illegalen Zugriff und segfaults.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top