1

私の課題に取り組んでいます。詳細は別の質問にあります。使用する場合

arr[(i * 16) % arrLen] *= 2; // seg fault

vs

arr[i % arrLen] *= 2; // OK!

なんで?完全なソースは31行目を参照してください。なぜですか?配列の長さをモジュラスするので、大丈夫ですか?

4

3 に答える 3

5

i * 16符号付き整数の負の範囲にオーバーフローする可能性があります。負の整数のモジュロを取ると、負の余りが得られ、配列の添え字が負になり、配列に割り当てられたメモリの外部にアクセスし、場合によってはクラッシュする可能性があります。

于 2012-09-26T11:07:08.433 に答える
1

intシステム上ののサイズが32ビットであると仮定すると、オーバーフローが発生し、その結果i * 16がマイナスになる可能性があります。2の補数システムでは、負の値はより高い2進値で表されます。

int reps = 256 * 1024 * 1024;

つまりreps = 268,435,456、これは、までループしている値です。iしたがって268,435,455、の最大値はとです268,435,455 * 16 = 4,294,967,280

32ビットintが表すことができる最大の正の値は2,147,483,6474,294,967,295の場合、unsigned intまだ負の値をラップしていない)です。これは、結果が負の値として解釈されていることを意味します。

からの負のオフセットへのアクセスarrは、割り当てられたメモリの範囲外です。これにより、未定義の動作が発生し、幸いなことにセグメンテーション違反が発生します。

于 2012-09-26T11:10:42.693 に答える
1

あなたの完全な情報源を見てください:

  1. あなたはそのメモリを取得できたことを確認するためにmallocのリターンをチェックする必要があります
  2. あなたはメモリを解放する必要があります、あなたはリークがあります
  3. arr配列内のメモリは初期化されていません。割り当てますが、何にも設定しないため、(ほとんどの場合)大きな負の数が得られます。これはによって行うことができますmemset(arr,0,arrLen);
  4. malloc(arrLen * sizeof(int))ただし、arrLenはで作成されているため/sizeof(int)、そこで作業をキャンセルしています...

セグメンテーション違反に関しては、他の人があなたのアレイがオーバーフローしていると述べているように。intの配列を作成しました。次に、0からintの最大サイズであるreps(268,435,456)にループします。これに16を掛けようとすると、オーバーフローして負のオフセットが作成されます。

担当者の初期化に16を掛けてみてください。

int reps = 256 * 1024 * 1024 * 16;

コンパイラは、この正確なことを知らせる警告をスローする必要があります。

warning: integer overflow in expression [-Woverflow]
于 2012-09-26T11:55:04.657 に答える