私の課題に取り組んでいます。詳細は別の質問にあります。使用する場合
arr[(i * 16) % arrLen] *= 2; // seg fault
vs
arr[i % arrLen] *= 2; // OK!
なんで?完全なソースは31行目を参照してください。なぜですか?配列の長さをモジュラスするので、大丈夫ですか?
i * 16
符号付き整数の負の範囲にオーバーフローする可能性があります。負の整数のモジュロを取ると、負の余りが得られ、配列の添え字が負になり、配列に割り当てられたメモリの外部にアクセスし、場合によってはクラッシュする可能性があります。
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,647
(4,294,967,295
の場合、unsigned int
まだ負の値をラップしていない)です。これは、結果が負の値として解釈されていることを意味します。
からの負のオフセットへのアクセスarr
は、割り当てられたメモリの範囲外です。これにより、未定義の動作が発生し、幸いなことにセグメンテーション違反が発生します。
あなたの完全な情報源を見てください:
memset(arr,0,arrLen);
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]