在another question中处理我的作业,更多细节。如果我使用
arr[(i * 16) % arrLen] *= 2; // seg fault
vs
arr[i % arrLen] *= 2; // OK!
为什么呢? Full source 请参阅第31行。为什么?我模数组的长度,所以应该没问题?
答案 0 :(得分:5)
i * 16
可以溢出到有符号整数的负范围内。当你取一个负整数的模数时,你可以得到一个负余数,这将使你的数组下标为负数,并导致在数组的已分配内存之外的访问,有时会崩溃。
答案 1 :(得分:1)
假设系统上int
的大小为32位,则可能导致溢出,i * 16
的结果变为负值。在二进制补码系统中,负值用更高的二进制值表示。
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
访问负偏移超出了已分配内存的范围,这会导致未定义的行为,幸运的是会出现seg错误。
答案 2 :(得分:1)
查看完整资料来源:
memset(arr,0,arrLen);
malloc(arrLen * sizeof(int))
但是arrLen是使用/sizeof(int)
创建的,所以你取消了那里的工作...... 关于你的seg错误,正如其他人已经声明你的阵列溢出。你已经创建了一个int数组。然后你从0循环到reps(268,435,456),这是int的最大大小。当你试图将它乘以16时,你会溢出并产生负偏移。
尝试将16乘以reps的初始化:
int reps = 256 * 1024 * 1024 * 16;
您的编译器应该发出警告,让您知道这一点:
warning: integer overflow in expression [-Woverflow]