1
#include <iostream> 

int foo(int i){ 
     return foo(i + 1);
} 

int main(int argc,char * argv[]){ 
     if(argc != 2){ 
         return 1; 
     } 
     std::cout << foo(std::atoi(argv[1])) << std::endl; 
} 

% clang++ -O2 test.cc

% 時間 ./a.out 42

1490723512

./a.out 42 0.00s ユーザー 0.00s システム 69% CPU 0.004 合計

% 時間 ./a.out 42

1564058296

./a.out 42 0.00s ユーザー 0.00s システム 56% CPU 0.006 合計

% g++ -O2 test.cc

% ./a.out 42 #無限再帰

^C

% clang++ --version 
clang version 3.3 (tags/RELEASE_33/final) 
Target: x86_64-apple-darwin12.4.0 
Thread model: posix 
% g++ --version 
i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00) 
Copyright (C) 2007 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions.  There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

それはバグですか、それともclang ++の機能ですか?

4

1 に答える 1

7

g++ と clang++ はどちらも C++98 と C++11 のコードをコンパイルできますが、clang++ は最初から C++11 コンパイラとして設計されており、その DNA に C++11 の動作が組み込まれています (いわば)。 .

C++11 では、C++ 標準がスレッド対応になりました。これは、特定のスレッド動作がいくつかあることを意味します。特に 1.10/24 の状態:

実装では、スレッドが最終的に次のいずれかを実行すると想定する場合があります。

— 終了、

— ライブラリ I/O 関数を呼び出します。

— 揮発性オブジェクトへのアクセスまたは変更、または

— 同期操作またはアトミック操作を実行します。

[注: これは、終了を証明できない場合でも、空のループの削除などのコンパイラ変換を許可することを目的としています。— エンドノート]

これこそが、最適化時に clang++ が行っていることです。関数に副作用がないことを確認し、終了しなくて削除します。

于 2013-08-28T01:59:23.897 に答える