Gleitkommaausnahme (SIGFPE) bei ‘int main(){ return(0); }’

Lesezeit: 8 Minuten

Benutzeravatar von Chimera
Chimäre

Ich versuche, ein einfaches C-Programm für zwei verschiedene Linux-Umgebungen zu erstellen. Auf einem Gerät läuft das Programm einwandfrei, auf dem anderen Gerät generiert das Programm eine Fließkommaausnahme. Das Programm gibt nur 0 von main zurück, was mich glauben lässt, dass es eine Inkompatibilität mit dem Startcode gibt, vielleicht ABI?

Das Programm wird mit gcc mit den folgenden Build-Spezifikationen kompiliert:

Verwenden von integrierten Spezifikationen. Ziel: i386-redhat-linux Konfiguriert mit: ../configure –prefix=/usr –mandir=/usr/share/man –infodir=/usr/share/info –enable-shared –enable-threads =posix –enable-checking=release –with-system-zlib –enable-__cxa_atexit –disable-libunwind-exceptions –enable-libgcj-multifile –enable-languages=c,c++,objc,obj-c++ ,java,fortran,ada –enable-java-awt=gtk –disable-dssi –disable-plugin –with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4. 2.0/jre –with-cpu=generic –host=i386-redhat-linux Thread-Modell: posix gcc Version 4.1.2 20080704 (Red Hat 4.1.2-52)

Die Programmquelle ist die folgende:

int main()
{
        return(0);
}

Auf dem Celeron-Gerät generiert dieses Programm unter GDB Folgendes:

[root@n00200C30AA2F jrn]# /jrn/gdb fail GNU gdb Red Hat Linux (5.3post-0.20021129.18rh) (gdb) run Starting program: /jrn/fail 

Program received signal SIGFPE, Arithmetic exception. 0x40001cce in ?? () (gdb) bt
#0  0x40001cce in ?? ()
#1  0x4000c6b0 in ?? ()
#2  0x40000cb5 in ?? ()

Unten sind die Details, die ich sammeln könnte, um herauszufinden, was passiert:

CELERON:  ( fails on this device )
2.6.8 #21 Mon Oct 1 11:41:47 PDT 2007 i686 i686 i386 GNU/Linux
============
[root@n00200C30AA2F proc]# cat cpuinfo 
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 9
model name      : Intel(R) Celeron(R) M processor          600MHz
stepping        : 5
cpu MHz         : 599.925
cache size      : 512 KB
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 2
wp              : yes
flags           : fpu vme de pse tsc msr mce cx8 sep mtrr pge mca cmov pat clflush dts acpi mmx fxsr sse sse2 tm pbe
bogomips        : 1179.64

GNU C Library stable release version 2.3.2, by Roland McGrath et al.
Compiled by GNU CC version 3.2.2 20030222 (Red Hat Linux 3.2.2-5).
Compiled on a Linux 2.4.20 system on 2003-03-13.
Available extensions:
        GNU libio by Per Bothner
        crypt add-on version 2.1 by Michael Glad and others
        linuxthreads-0.10 by Xavier Leroy
        BIND-8.2.3-T5B
        libthread_db work sponsored by Alpha Processor Inc
        NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk

ATOM:  ( works fine on this device )
2.6.35 #25 SMP Mon Mar 12 09:02:45 PDT 2012 i686 i686 i386 GNU/Linux
==========
[root@n00E04B36ECE5 ~]# cat /proc/cpuinfo 
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 28
model name      : Genuine Intel(R) CPU N270   @ 1.60GHz
stepping        : 2
cpu MHz         : 1599.874
cache size      : 512 KB
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 10
wp              : yes
flags           : fpu vme de tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx constant_tsc up arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl est tm2 ssse3 xtpr pdcm movbe lahf_lm
bogomips        : 3199.74
clflush size    : 64
cache_alignment : 64
address sizes   : 32 bits physical, 32 bits virtual
power management:


GNU C Library stable release version 2.5, by Roland McGrath et al.
Compiled by GNU CC version 4.1.2 20080704 (Red Hat 4.1.2-44).
Compiled on a Linux 2.6.9 system on 2009-09-02.
Available extensions:
        The C stubs add-on version 2.1.2.
        crypt add-on version 2.1 by Michael Glad and others
        GNU Libidn by Simon Josefsson
        GNU libio by Per Bothner
        NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk
        Native POSIX Threads Library by Ulrich Drepper et al
        BIND-8.2.3-T5B
        RT using linux kernel aio
Thread-local storage support included.

Was kann ich tun, um festzustellen, was dieses Problem verursacht? Wie wäre es mit dem Versuch, statisch mit einer bestimmten Version von libc zu verknüpfen?

Nachdem unter GDB ein Fehler auftritt, führe ich Folgendes aus:

(gdb) x/1i $eip
0x40001cce:     divl   0x164(%ecx)
(gdb) info reg
eax            0x6c994f 7117135
ecx            0x40012858       1073817688
edx            0x0      0
ebx            0x40012680       1073817216
esp            0xbffff740       0xbffff740
ebp            0xbffff898       0xbffff898
esi            0x8049580        134518144
edi            0x400125cc       1073817036
eip            0x40001cce       0x40001cce
eflags         0x10246  66118
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x0      0
(gdb) x/1wx 0x164+$ecx
0x400129bc:     0x00000000
(gdb) 

Basierend auf der Hilfe, die ich erhalten habe, scheint es, dass der libc-Startcode aus irgendeinem Grund durch 0 dividiert wird.

Die Frage ist nun, was dieses offensichtlich schlechte Verhalten verursacht? Etwas muss mit etwas anderem nicht kompatibel sein?

Montageausgabe:

[jrn@localhost ~]$ more fail.s
        .file   "fail.c"
        .text
.globl main
        .type   main, @function
main:
        leal    4(%esp), %ecx
        andl    $-16, %esp
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ecx
        movl    $0, %eax
        popl    %ecx
        popl    %ebp
        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
        .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-52)"
        .section        .note.GNU-stack,"",@progbits

  • Und selbst gcc 4.1.2 ist wirklich alt. Aktuelle GCC-Version ist 4.7!

    – Basile Starynkevitch

    24. September 2012 um 18:09 Uhr

  • GCC ist in die Revisionshölle von Firefox gefahren. Sie werden bald sehen, dass wir in wenigen Tagen mit GCC 25.3 konfrontiert werden!

    Benutzer529758

    24. September 2012 um 18:10 Uhr

  • Es könnte auch sein libc oder libstdc++ verbunden. Beide haben einen nicht-trivialen Initialisierungscode. Ich würde ihre installieren -dbg Pakete und versuchen Sie es zu verwenden gdb um das Problem zu debuggen. Viel Glück, du wirst es brauchen.

    – Basile Starynkevitch

    24. September 2012 um 18:10 Uhr


  • Kannst du ein x/1i $eip wann bekommt man die FPE unter GDB?

    – ninjalj

    24. September 2012 um 19:06 Uhr

  • @Chimera: Nein, das ist eine sehr schlechte Idee. Höchstwahrscheinlich wird es danach sehr bald wieder abstürzen, aber selbst wenn Sie es zum Laufen bringen können, könnte es wahrscheinlich anfangen, zufällige andere Fehler an völlig unabhängigen Stellen zu verursachen.

    – Adam Rosenfield

    24. September 2012 um 19:48 Uhr

Benutzeravatar von nneonneo
nneonneo

Das hört sich nach einem wirklich langen Schuss an … aber können Sie Folgendes versuchen?

$ readelf -a fail

und nach einem dynamischen GNU_HASH-Tag suchen? Meine Vermutung ist, dass die Binärdatei verwendet wird GNU_HASHund dein ld.so ist zu alt, um es zu verstehen. Unterstützung für den GNU-Hash-Abschnitt wurde glibc um 2006 hinzugefügt, und Mainline-Distributionen begannen um 2007 oder 2008 nur noch GNU-Hash zu sein. Ihr Centrino glibc ist von 2003das älter als GNU-Hashing ist.

Wenn die ld.so GNU-Hash nicht versteht, wird stattdessen versucht, den alten ELF-Hash-Abschnitt zu verwenden, der leer ist. Insbesondere vermute ich, dass Ihr Absturz bei auftritt diese Zeile ein elf/do-lookup.h:

for (symidx = map->l_buckets[hash % map->l_nbuckets];

Da der Linker vermutlich keine GNU-Hashes versteht, l_nbuckets wäre 0, was zum Absturz führen würde. Beachten Sie, dass map ist eine große Struktur mit rund 100 Strukturelementen und l_nbuckets ist um das 90. Mitglied der Struktur in neueren ld.so (0x164 = 4*89also in älter ld.so es ist wahrscheinlich genau dieses Mitglied).

Um zu sehen, ob dies der Fall ist schlüssig das problem, bauen mit -Wl,--hash-style=sysv oder -Wl,--hash-style=both und schau ob der Absturz weg ist.

  • Danke … wenn ich morgen früh ins Büro komme, werde ich es versuchen.

    – Chimäre

    25. September 2012 um 5:59 Uhr

  • Wow. Einfach wow. Schöne Analyse. +1, unabhängig davon, ob es das Problem für das OP behebt

    – sehen

    25. September 2012 um 6:40 Uhr

  • Ja – es ist ein so guter Versuch, dass es richtig sein sollte (auch wenn der Name des Posters nie zu enden scheint). +1.

    – Martin Jakob

    25. September 2012 um 8:34 Uhr


  • Sie, Sir, verfügen über hervorragende Fähigkeiten zur psychischen Fehlersuche. Raymond Chen wäre stolz.

    – Adam Rosenfield

    25. September 2012 um 14:25 Uhr

  • Du rockst! Das war das Problem. Das Kompilieren mit -Wl,–hash-style=both generiert eine ausführbare Datei, die sowohl in älteren als auch in neueren Umgebungen funktioniert.

    – Chimäre

    25. September 2012 um 16:07 Uhr

Benutzeravatar von syplex
Syplex

Da es auf dem ATOM funktioniert, aber nicht auf dem älteren Celeron, könnte das Problem bei einer Compiler-Optimierung liegen, die Code generiert, den der Celeron nicht ausführen kann. Versuchen Sie, mit dem Flag -O0 zu kompilieren. Außerdem würde ich vorschlagen, -march=i686 hinzuzufügen, um die Architektur explizit anzugeben. Um das Problem einzugrenzen, würde ich auch vorschlagen, die Verknüpfung mit der C++-Laufzeitumgebung und JAVA zu deaktivieren.

Haben Sie dieses Testprogramm einmal erstellt und auf jedem Gerät ausgeführt, oder haben Sie für jedes Gerät eine andere ausführbare Datei erstellt? Wenn Sie eine ausführbare Datei erstellen, haben Sie möglicherweise unterschiedliche Versionen von libc, libstdc++ auf den beiden Geräten oder auf den Geräten im Vergleich zu Ihrem Build-Computer.

  • Die Compiler-Flags machten keinen Unterschied, gleiches Ergebnis. Und ja, auf einem Computer aufbauen und die ausführbare Datei auf zwei verschiedenen Geräten ausführen. In der Atom-Geräteumgebung wird libc 2.5 ausgeführt (das ist dasselbe wie auf der Build-Maschine). Das Gerät, auf dem die ausführbare Datei fehlschlägt, hat jedoch libc 2.3.2. Vielleicht gibt es also ein Abwärtskompatibilitätsproblem mit libc 2.3.2 und libc 2.5?

    – Chimäre

    24. September 2012 um 22:50 Uhr

  • Was ist mit glibcxx oder libstdc++? Verknüpfen Sie auch eine dieser Bibliotheken statisch? Ich würde vorschlagen, zu versuchen, gegen den kleinsten gemeinsamen Nenner von libc 2.3.2 und was auch immer dieses Gerät für c++ hat, zu bauen.

    – Syplex

    24. September 2012 um 23:02 Uhr

  • Nichts statisch verlinken. [jrn@localhost ~]$ ldd Fehler linux-gate.so.1 => (0x0098f000) libc.so.6 => /lib/libc.so.6 (0x00bb0000) /lib/ld-linux.so.2 (0x00b91000)

    – Chimäre

    24. September 2012 um 23:04 Uhr

  • Build gegen eine ältere Version von libc (zB 2.3.2). Dies verursacht höchstwahrscheinlich Ihr Problem.

    – Syplex

    24. September 2012 um 23:16 Uhr

  • Ja, das ist auch mein Verdacht, aber wir versuchen, einen Weg zu finden, unsere Build-Umgebung auf neuere Bibliotheken usw. zu aktualisieren, aber trotzdem in der Lage zu sein, ausführbare Dateien zu erstellen, die mit mehreren Geräten kompatibel sind, die unterschiedliche Versionen von libc haben. Wir stecken also möglicherweise fest und der ultimative Weg nach vorne besteht darin, in den sauren Apfel zu beißen und die Umgebung für die älteren Legacy-Geräte zu aktualisieren.

    – Chimäre

    24. September 2012 um 23:29 Uhr

1416860cookie-checkGleitkommaausnahme (SIGFPE) bei ‘int main(){ return(0); }’

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy