2016-05-25 18 views
2

IAR EWARMコンパイラを使用してCでこれを実行します。IARコンパイラのポインタ

uint8_t packet[2048]; 
uint32_t* src = (uint32_t*)&packet[9]; 
uint32_t var = *src++; 

この最後の行でバスフォールトが発生します。

uint8_t packet[2048]; 
uint32_t* src = (uint32_t*)&packet[9]; 
uint32_t var = 0xFE; 
*src++; 

ここではバス障害はありません。私はそれが私が指すと期待しているデータへのデバッガのsrcポイントを見ることができます。インクリメントは期待通りに機能しますが、それを読み取ろうとするとバス障害が発生します。

助けが必要ですか?

+0

これは情報のランダムなまとまりです。答えるだけでなく、尋ねられたことを理解することさえも不十分です。 –

+0

私には明らかです。あなたは私の関数のプロトタイプを持っています。ポインタを渡すときにポインタをどのように参照するかを見ることができます。実際の関数呼び出しがあります。そして、実際のエラーとともにエラーが発生した関数の実際の行があります。 – lusher00

+0

ちょうどFYI - 現時点ではっきりしない3つの近い票があります。 –

答えて

4

MCUは32ビットの整数の読み込みを32ビットに合わせる必要があります。

&packet[9]は、32ビットアラインメントではありません。そのため、あなたには間違いがあります。

+0

うん、そうです。私はそれについてすべて忘れてしまった。ありがとうございました。 – lusher00

4

&packet[9]は、おそらくuint32_tで正しく位置合わせされていません。 ARM CPUの "バスエラー"がアラインメントエラーの兆候であることがよくあります。アライメントの説明についてはSee hereを参照してください。

2番目の例では、決して結果を使用しないので、*オペレーションを最適化することによってバス障害を回避することができます。

これを修正しても、厳密なエイリアシング規則に違反すると、コードで未定義の動作が発生することに注意してください。 (uint8_tには、uint32_tという別名を付けることはできません)。コンパイラの中には現在正しく動作しているように見えるかもしれませんが、コードは将来いつでも破損する可能性があります。

あなたのコードの安全相当するものは次のようになります。

uint8_t *src = &packet[9]; 
uint32_t var; 
memcpy(&var, src, sizeof var); 
src += sizeof var; 

注ソースデータが整数のための特定のバイトオーダーを持つものとして指定されている場合は、データとは対照的に、(例えば、あなたがネットワークストリームからそれを取得していること先に同じメソッドで保存した場合)、uint32_tの表現に依存しないデータを読み取るメソッドを使用することができます。 (言い換えれば、「エンディアン」)。

関連する問題