2013-08-07 19 views
7

我注意到g++抱怨有點太嚴格有關crossed initialization,我不知道爲什麼這些假陽性錯誤可能不只是在看節目的SSA形式在編譯時被刪除。在C++中過度使用「跨變量初始化」錯誤?

我舉一個很簡單的例子:

#include <cstdlib> 

int main() 
{ 
    goto end; 

    int i = 0; // unused variable declaration 

end: 
    return EXIT_SUCCESS; 
} 

g++ -Wall -Wextra -o example1 example1.ccg++ 4.8.1)編譯,編譯器提供了以下錯誤信息:

example1.cc: In function ‘int main()’: 
example1.cc:10:2: error: jump to label ‘end’ [-fpermissive] 
    end: 
^
example1.cc:6:8: error: from here [-fpermissive] 
    goto end; 
     ^
example1.cc:8:7: error: crosses initialization of ‘int i’ 
    int i = 0; 
    ^
example1.cc:8:7: warning: unused variable ‘i’ [-Wunused-variable] 

所以,這將提高由於變量未被使用而實際上沒有風險的錯誤(編譯器顯然同時具有信息並且不能將其組合以推斷錯誤是假陽性)。

更奇怪了,我希望LLVM是在分析程序更有效率。所以,我在clang++ -Wall -Wextra -o example1 example1.ccclang++ 3.4)這個簡單的例子上試了clang++(LLVM)。而且,我得到了相同的錯誤消息:

example1.cc:8:7: warning: unused variable 'i' [-Wunused-variable] 
    int i = 0; 
    ^
example1.cc:6:3: error: goto into protected scope 
    goto end; 
^
example1.cc:8:7: note: jump bypasses variable initialization 
    int i = 0; 
    ^
1 warning and 1 error generated. 

所以,我敢肯定,我很想念這裏一些重要的東西,使這個假陽性更難檢測比我雖然問題。但是,我不知道它是什麼。或者,C++規範特別說明它必須是這樣的。

如果有人有一個想法,隨時分享!

編輯:我也編譯C(gccclang)完全相同的代碼,並且它去罰款只是警告有關i是未使用的變量。因此,它強化了這一事實,即這更可能與C++的規範相關聯,而不是在編譯時檢測到此問題的問題。

+0

是不是代碼不管變量'int是使用i'或不生病,怎樣形成的?編譯器抱怨不符合規範的代碼,而不是不可編譯的代碼。 – Walter

+1

這兩個編譯器都完全按照標準規定的方式執行。不允許跨越初始化,完全停止,故事結束。沒有什麼可以分析的。 –

+0

好的,這是我錯過的。這主要來自C++的規範,並不是因爲存在潛在的技術問題。 – perror

回答

10

沒有什麼不對的編譯器。根據標準,你的代碼是不合格的。

你的具體情況,該標準的要求可能不是必要的,跳躍,可以允許和編譯器可以創建有效的代碼。但是,這只是因爲變量int i的初始化沒有副作用。

你可以讓你的代碼有效,只需封閉跳下部分在它自己的範圍:

#include <cstdlib> 

int main() 
{ 
    goto end; 
    { 
    int i = 0; // unused variable declaration 
    } 
end: 
    // cannot use i here, as it's not defined. 
    return EXIT_SUCCESS; 
} 
+0

在說明書中說明了什麼地方?我找不到... – perror

8

這是不允許的,因爲有可能你會叫未正確構造的對象的析構函數。無可否認,int沒有構造函數或析構函數,但它對所有類型的對象都是「公平的」。從技術上講,標籤end:可能使用i,並且通過嚴格規則,它可以防止機器檢查每一條代碼路徑(這會成爲「暫停問題」)。