Hier ist ein Stück Code, das ich habe zu kompilieren versucht:Super seltsame segfault mit gcc 4.7 - Bug?
#include <cstdio>
#define N 3
struct Data {
int A[N][N];
int B[N];
};
int foo(int uloc, const int A[N][N], const int B[N])
{
for(unsigned int j = 0; j < N; j++) {
for(int i = 0; i < N; i++) {
for(int r = 0; r < N ; r++) {
for(int q = 0; q < N ; q++) {
uloc += B[i]*A[r][j] + B[j];
}
}
}
}
return uloc;
}
int apply(const Data *d)
{
return foo(4,d->A,d->B);
}
int main(int, char **)
{
Data d;
for(int i = 0; i < N; ++i) {
for(int j = 0; j < N; ++j) {
d.A[i][j] = 0.0;
}
d.B[i] = 0.0;
}
int res = 11 + apply(&d);
printf("%d\n",res);
return 0;
}
Ja, es ziemlich seltsam aussieht, und im Moment etwas Sinnvolles überhaupt nicht tut, aber es ist die knappste Version von einem viel größeren Programm, mit dem ich anfangs das Problem hatte.
Es kompiliert und läuft nur mit GCC (G ++) fein 4.4 und 4.6, aber wenn ich GCC verwenden 4.7 und dritte Ebene Optimierungen ermöglichen:
g++-4.7 -g -O3 prog.cpp -o prog
ich einen Segmentation Fault erhalten, wenn es ausgeführt wird. GDB nicht wirklich viele Informationen geben, was schief gelaufen ist:
(gdb) run
Starting program: /home/kalle/work/code/advect_diff/c++/strunt
Program received signal SIGSEGV, Segmentation fault.
apply ([email protected]=0x7fffffffe1a0) at src/strunt.cpp:25
25 int apply(const Data *d)
(gdb) bt
#0 apply ([email protected]=0x7fffffffe1a0) at src/strunt.cpp:25
#1 0x00000000004004cc in main() at src/strunt.cpp:34
Ich habe versucht, den Code auf unterschiedliche Weise zwicken, um zu sehen, ob der Fehler verschwindet. Es scheint notwendig zu sein, alle vier Schleifenebenen in foo zu haben, und ich war nicht in der Lage, sie durch eine einzige Ebene von Funktionsaufrufen zu reproduzieren. Oh ja, die äußerste Schleife muss einen vorzeichenlosen Schleifenindex verwenden.
Ich fange an zu vermuten, dass dies ein Fehler im Compiler oder in der Laufzeit ist, da es für Version 4.7 spezifisch ist und ich nicht sehen kann, welche Speicherzugriffe ungültig sind.
Jeder Einblick in das, was vor sich geht, würde sehr geschätzt werden.
Es ist möglich, die gleiche Situation mit der C-Version von GCC mit einer leichten Änderung des Codes zu erhalten.
Mein System ist:
Debian sid Linux 3.2.0-4-amd64 GCC 4.7.2-5
Okay, so habe ich mir die Demontage von GDB angeboten, aber ich hab angst das es mir nicht viel sagt:
Dump of assembler code for function apply(Data const*):
0x0000000000400760 <+0>: push %r13
0x0000000000400762 <+2>: movabs $0x400000000,%r8
0x000000000040076c <+12>: push %r12
0x000000000040076e <+14>: push %rbp
0x000000000040076f <+15>: push %rbx
0x0000000000400770 <+16>: mov 0x24(%rdi),%ecx
=> 0x0000000000400773 <+19>: mov (%rdi,%r8,1),%ebp
0x0000000000400777 <+23>: mov 0x18(%rdi),%r10d
0x000000000040077b <+27>: mov $0x4,%r8b
0x000000000040077e <+30>: mov 0x28(%rdi),%edx
0x0000000000400781 <+33>: mov 0x2c(%rdi),%eax
0x0000000000400784 <+36>: mov %ecx,%ebx
0x0000000000400786 <+38>: mov (%rdi,%r8,1),%r11d
0x000000000040078a <+42>: mov 0x1c(%rdi),%r9d
0x000000000040078e <+46>: imul %ebp,%ebx
0x0000000000400791 <+49>: mov $0x8,%r8b
0x0000000000400794 <+52>: mov 0x20(%rdi),%esi
Was soll ich sehen wenn ich mir das anschaue?
Bearbeiten 2015-08-13: Dies scheint in g ++ 4.8 und später behoben werden.
Ja, es ist ein Fehler. Sehen Sie sich die generierte Assembly von dort an, wo sie segmentiert. – PlasmaHH
Ich wusste, dass Sie Argumentnamen in einem Funktionsprototyp auslassen können, aber ich habe nie gesehen, dass jemand die Namen in einer tatsächlichen Funktionsdefinition ausgelassen hat. – user2357112
sieht aus wie es mit 4,6 entweder: http://coliru.stacked-crooked.com/a/1d50e7c5360796e6 – marcinj