2013-02-16 4 views
6

Nun, ich habe die Artikel über SIGFPE gesucht, dann habe ich ein paar Tests geschrieben, aber es ist merkwürdig. Dann muss ich es hier posten, um Hilfe zu erbitten. Ist GCC/G ++ oder ISO C++ klar definiert, was passiert, wenn durch Null geteilt wird?Was macht C/C++ - Handler SIGFPE?

1) ich den Artikel gesucht: Division by zero does not throw SIGFPE Sames es die Ausgabe

2) inf ist, wenn ich es wie folgt umschreiben:

void signal_handler (int signo) { 
    if(signo == SIGFPE) { 
     std::cout << "Caught FPE\n"; 
    } 
} 

int main (void) { 
    signal(SIGFPE,(*signal_handler)); 

    int b = 1; 
    int c = 0; 
    int d = b/c; 
    //fprintf(stderr,"d number is %d\n,d); 
    return 0; 
} 

dann signal_handler wird geschieht nicht. aber wenn ich die Zeile

auskommentieren dann ruft signal_handler weiter.

kann jemand es erklären?

+0

Integer Division durch Null noch erhöht 'SIGFPE' (Floating-Point-Fehler), aber durch Nullpunkt Teilung Floating ergibt unendlich als Antwort. –

+0

'int c = 0; int d = b/c; '? was bedeutet "b/0"? – billz

+0

Ich wiederhole dich nicht genau: Ich bekomme das Signal nur einmal und dann wird das Programm beendet, mit oder ohne 'printf'. Wenn ich 'signal (SIGFPE, (* signal_handler));' innerhalb des Signal-Handlers hinzufüge, dann reproduziere ich Sie. Linux 3.10, gcc 4.7.3. –

Antwort

5

Dies ist interessant: Mit der fprintf auskommentiert, hat der Compiler festgestellt, dass das berechnete Ergebnis: d = b/c ist ein ungenutzter lokaler Ausdruck und kann weg optimiert werden.

Offensichtlich ist es in seiner Ausführung jedoch nicht frei von Seiteneffekten, aber der Compiler kann zu diesem Zeitpunkt nichts über die Laufzeitumgebung feststellen. Ich bin überrascht, dass die statische Analyse dies nicht als Warnung (zumindest) in einem modernen Compiler auffasst.

@vonbrand hat Recht. Sie haben Glück mit dem, was Sie im (asynchronen) Signal-Handler tun.


Edit:, wenn Sie sagen "signal_handler hält calling", meinst du es zu wiederholen unbegrenzt? Wenn dies der Fall ist, kann es zu Problemen mit dem Systemneustart kommen. Versuchen Sie: siginterrupt(SIGFPE, 1); (vorausgesetzt, es ist verfügbar).

3

Es gibt nur wenige Operationen in Signal-Handler erlaubt, und unter Verwendung eines beliebigen gepufferte I/O (std::cout et al, aber auch fprintf(3), die BTW ich weiß nicht, ob es gut mit dem vorherigen mischt) ist aus die Frage. Die Einschränkungen finden Sie unter signal(7).

1

Ist die GCC/G ++ oder ISO C++ klar definiert, was passiert, wenn durch Null teilen?

Soweit der Standard geht, Division durch Null ist Undefined Behavior, alles könnte passieren.

In der Praxis, obwohl der Standard sagt, dass es UB ist, ist es tatsächlich implementation-defined auf der Ebene des Betriebssystems (nicht Sprache/Compiler). Auf POSIX wird dies in der Tat eine SIGFPE erzeugen, unter Windows wird eine Ausnahme (Windows' SEH Ausnahme, nicht eine C++ Ausnahme, obwohl einige Compiler zusätzlich ++ Ausnahmen SEH bis C Karte) werfen usw.

wenn ich Kommentar- die Zeile //fprintf(stderr,"d number is %d\n,d); dann ruft signal_handler weiter. kann jemand das erklären?

Wie andere gesagt haben, ist dies, weil der Compiler erkennt, dass d nie verwendet und optimiert die Berechnung (sowie die b und c Definitionen aller Wahrscheinlichkeit nach) entfernt. Dies geschieht, weil die Sprache nicht vorhersehen kann, was passieren wird (denken Sie daran, es ist UB), also könnte es genauso gut davon ausgehen, dass nichts passiert.

3

Warum signal_handler wird nicht passieren: Compiler-Optimierung tötete Division für nicht verwendete Ergebnis.

Warum signal_handler weiter ruft: Nach der Rückkehr vom Signalhandler führt FPE dieselbe Anweisung erneut aus. Sie können es vermeiden, indem Sie longjmp verwenden.

Hier ist mein gut funktionierenden Code für den Zweck (zumindest unter Mac OS X) https://github.com/nishio/learn_language/blob/master/zero_division/zero_division.cpp

+0

Scheint auch auf 'g ++' und 'clang ++' auf 'ubuntu' zu arbeiten – ubershmekel