下面是一段代碼,我一直在試圖編譯:超級奇怪段錯誤與海灣合作委員會4.7 - 錯誤?
#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;
}
是的,這看起來很奇怪,在所有的時刻沒有做什麼有用的,但它是最簡潔的版本我最初遇到問題的一個更大的程序。
它編譯和運行只需用GCC(G ++)4.4和4.6罰款,但如果我使用GCC 4.7,並啓用第三級優化:
g++-4.7 -g -O3 prog.cpp -o prog
我運行時,它得到一個分段錯誤。 GDB並沒有真正給出了什麼差錯多的信息:
(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
我試着調整方式不同的代碼,看看錯誤消失。似乎有必要在foo中擁有所有四個循環級別,並且我無法通過調用一個函數級別來重現它。哦,是的,最外層的循環必須使用無符號循環索引。
我開始懷疑這是編譯器或運行時的錯誤,因爲它特定於版本4.7,我無法看到哪些內存訪問無效。
任何深入瞭解正在發生的事情將非常感激。
通過對代碼進行輕微修改,可以獲得與G-C版本相同的情況。
我的系統是:
Debian的喘息 的Linux 3.2.0-4,AMD64 GCC 4.7.2-5
好了,所以我看着由GDB提供的拆卸,但我對我來說恐怕不多說:
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
我看到這個時應該看到什麼?
編輯2015-08-13:這似乎是固定在g ++ 4.8和更高版本。
是的,它的一個錯誤。看看它在段落所在位置生成的組件。 – PlasmaHH
我知道你可以省略函數原型中的參數名稱,但我從來沒有見過任何人在實際函數定義中省略過名稱。 – user2357112
看起來像4.6失敗一樣:http://coliru.stacked-crooked.com/a/1d50e7c5360796e6 – marcinj