2012-02-29 3 views
20

次のコードを検討:g ++がIRQによって変更可能な変数によって制御されるループを最適化しないようにする方法はありますか?

unsigned global; 
while(global); 
global

はIRQによって呼び出される関数に変更されます。しかし、g ++は "is-not-zero"テストを取り除き、whileループを無限ループに変換します。

コンパイラの最適化を無効にすると問題は解決しますが、C++ではそのための言語構成が用意されていますか?

+0

@ Styne666:タイトルは質問 – Necrolis

+0

も参照してください。http://stackoverflow.com/q/7083482/594137 –

+0

@ Styne666 - 特定のコンパイラ構成を必要とするコードを書くのは良い習慣ではありません。したがって、最適化を無効にすることは、実動コードのオプションにはなりません。 – 0xbadf00d

答えて

17

volatileとして変数を宣言します。

volatile unsigned global; 

これはglobalは異なるスレッドで変更することができ、すべての最適化は、それをオフにする必要があり、コンパイラに指示するキーワードです。

+1

"すべての最適化"を "特定の最適化"に置き換えることができます。まだ適用できる最適化がたくさんあるためです。例: 'global = 5 + 6;'では、あなたのステートメントは '5 + 6'が縮小されていないことを意味するかもしれません。 –

+2

volatile修飾子を追加しても、作成されたオペコードは変更されません。それはまだ無限ループに変換されます... – 0xbadf00d

+0

@SaschaHollはいそうです。別のスレッドで 'global'を' 0'に設定すると、ループは終了します。 –

0

あなたは、GCCは、機能ごとに最適化を無効にするには、関数の宣言に属性を使用できます。

void myfunc() __attribute__((optimize(0))); 

詳細についてはGCC Function Attributesページを参照してください。

+0

変数がメモリの特定のセクションになければならない場合は、 'section' [変数属性](http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html)を使用して正しく配置します。また、「volatile」とマークする必要があります。 –

7

あなたはGCCを使用していて、変数volatileを作ることは動作しないと言うので、あなたはループがコンパイラに横たわって変数を変更することを考えることにオプティマイザをだますことができます。

while(global) 
    asm volatile("" : "+g"(global)); 

これは、それが変数を変更したことを示すインラインアセンブリステートメント(入出力オペランドとして渡されます)。しかし、それは空ですので、明らかに実行時に何もしません。それでも、オプティマイザは変数を変更すると考えています。プログラマはそう言いましたが、オペランドの置換(単にテキストを別のものに置き換えることを意味します)を禁止するコンパイラは、実際にインラインアセンブリの本体を気にせず、それに面白いこと。

本体が空であり、制約が最も一般的なものを使用できるため、GCCがインラインアセンブリをサポートするすべてのプラットフォームで確実に動作するはずです。

+0

私は、このトリックは実際に動作することを確認することができます!ありがとうございました。 –

関連する問題