2010-05-02 109 views
0

我通過以下命令編譯我的代碼浮動例外:使用ICC編譯

icc -ltbb test.cxx -o test 

然後,當我運行程序:

time ./mp6 100 > output.modified 
Floating exception 
4.871u 0.405s 0:05.28 99.8%  0+0k 0+0io 0pf+0w 

我得到一個「浮動的例外」。在C++此以下是代碼,我異常之前和之後有:

// before 
if (j < E[i]) { 
    temp += foo(0, trr[i], ex[i+j*N]); 
} 

// after 
temp += (j < E[i])*foo(0, trr[i], ex[i+j*N]); 

這是布爾代數...所以(j < E [I])要麼將是一個0或1,因此乘法會導致0或foo()結果。我不明白爲什麼這會導致浮動異常。 這是FOO()的作用:

int foo(int s, int t, int e) { 
    switch(s % 4) { 
     case 0: 
      return abs(t - e)/e; 
     case 1: 
      return (t == e) ? 0 : 1; 
     case 2: 
      return (t < e) ? 5 : (t - e)/t; 
     case 3: 
      return abs(t - e)/t; 
    } 
    return 0; 
} 

FOO()不是我寫的,所以我也不太清楚,什麼它的功能...但我不認爲這個問題是與函數foo()。有沒有關於布爾代數的東西,我不明白,或者在C++中的作用與我所知的不同?任何想法爲什麼這會導致異常?

感謝, 斯托伊奇

+0

你是什麼意思「浮動異常」?請發佈確切的錯誤消息。 – 2010-05-02 04:59:36

+0

是'i','j','N'等所有整數? – Gabe 2010-05-02 05:01:59

+0

@加貝。是的,他們都是整數。 @Marcelo。這就是我擁有的所有信息。這是打印到終端的唯一的東西。 「浮動異常」。 – Hristo 2010-05-02 05:06:34

回答

3

你幾乎可以肯定爲零foo分裂。

int main() 
{ 
    int bad = 0; 
    return 25/bad; 
} 

一個簡單的程序也打印

Floating point exception

我的系統上。

所以,你應該檢查e是否爲0,當s % 4爲零,或者是否t爲0時s % 4爲2或3。然後返回任何價值是有道理的,您的情況,而不是試圖除以零。


@hristo:即使左側爲零,C++仍會評估乘法的右側。沒關係,結果 應該是零;重要的是 foo被調用並評估並導致錯誤。

樣品源:

#include <iostream> 
int maybe_cause_exception(bool cause_it) 
{ 
    int divisor = cause_it ? 0 : 10; 
    return 10/divisor; 
} 

int main() 
{ 
    std::cout << "Do not raise exception: " << maybe_cause_exception(false) << std::endl; 

    int x = 0; 

    std::cout << "Before 'if' statement..." << std::endl; 

    if(x) 
    { 
     std::cout << "Inside if: " << maybe_cause_exception(true) << std::endl; 
    } 

    std::cout << "Past 'if' statement." << std::endl; 

    std::cout << "Cause exception: " << x * maybe_cause_exception(true) << std::endl; 

    return 0; 
} 

輸出:

Do not raise exception: 1

Before 'if' statement...

Past 'if' statement.

Floating point exception

+0

那麼爲什麼它會第一次比較第二次... foo()的參數是完全一樣的? – Hristo 2010-05-02 05:10:04

+0

@Hristo:第一次,'foo'沒有被調用導致崩潰的參數。 – 2010-05-02 05:15:09

+0

因爲在第一個變體中函數只在'j 2010-05-02 05:19:15

1

是否有可能除以0?它可能是一個整數除0作爲浮動異常浮出水面。

當您有if時,如果除數爲0,則計算沒有完成。當您執行「布爾代數」時,無論如何都會進行計算,從而導致除以0錯誤。

你以爲它會是temp += 0*foo(...);所以它不需要調用foo(因爲0次任何東西總是0),但這不是編譯器的工作方式。必須評估*的雙方。

+0

這是可能的,但唯一改變的是我乘以'(j Hristo 2010-05-02 05:13:18

+0

不......我並不是在想foo()不會被調用,而是在考慮它會評估爲0.我不認爲foo()會導致異常,因爲參數是相同的。 – Hristo 2010-05-02 05:36:56

0

當我建議用乘以1或零代替分支時,我並不認爲如果陳述可能會防範數值異常。乘法技巧仍然評估表達式,但實際上將其拋棄。對於足夠小的表情來說,這種把戲比有條件的要好,但是你必須確保表情可以評估。

如果稍微改變了分母,你仍然可以使用乘法技巧。 而不是x/t使用x/(t + !t)如果分母不爲零,則不會影響任何內容(您正在加零),但允許分母t = 0被計算,然後通過乘以零丟棄。

對不起,但要小心我的建議,我不知道你的程序的所有細節。另外,我傾向於用「聰明的」布爾表達式替換分支

+0

是的我試過你的乘法技巧的建議,但問題是'if'阻止foo()導致異常,並且當我使用乘法時,foo()不再受保護並導致浮動異常。我不能編輯foo(),所以我不得不保留'if'語句。感謝您的建議! – Hristo 2010-05-03 01:42:47

1

雖然我沒有告訴你浮點異常的確切原因,但我可以提供一些信息,這些信息可能對調查未來的浮點異常有用,點錯誤。我相信Mark已經闡明瞭爲什麼你有這個特殊問題。


確定是否發生了浮點異常狀態,其原因是使用由C99在fenv.h提供的浮點異常設施的最簡便的方式。在fenv.h中定義了11個用於處理浮點環境的函數(請參閱fenv(3) man page)。您也可能會發現this article有趣。


在POSIX兼容的系統中時執行錯誤的算術運算,SIGFPE被髮送到一個進程,該不一定涉及浮點運算。如果處理了SIGFPE信號,並在sa_flags中指定了SA_SIGINFO用於呼叫sigaction(2),則siginfo_t結構的si_code成員應指定故障原因。

wikipedia SIGFPE article

一個常見的監督是由零考慮分割的SIGFPE條件的唯一來源。在某些體系結構(IA32包含[需要的引用])中,INT_MIN(最小的可表示的負整數值)-1的整數除法會觸發信號,因爲商數(正數)不可表示。