处理我的任务,另一个问题的更多细节。如果我使用
arr[(i * 16) % arrLen] *= 2; // seg fault
对比
arr[i % arrLen] *= 2; // OK!
为什么?完整来源见第 31 行。为什么?我对数组长度取模,所以应该没问题?
i * 16
可以溢出到有符号整数的负范围内。当您对负整数取模时,您可以获得负余数,这将使您的数组下标为负数,并导致访问数组分配的内存之外,有时还会导致崩溃。
查看您的完整来源:
memset(arr,0,arrLen);
malloc(arrLen * sizeof(int))
arrLen 是使用 a 创建的/sizeof(int)
,因此您正在取消那里的工作...关于您的段错误,正如其他人所说的那样,您的数组溢出了。您已经创建了一个整数数组。然后你从 0 循环到 reps (268,435,456),这是 int 的最大大小。当您尝试将其乘以 16 时,您会溢出并创建负偏移。
尝试将 16 乘以代表的初始化:
int reps = 256 * 1024 * 1024 * 16;
你的编译器应该抛出一个警告,让你知道这个确切的事情:
warning: integer overflow in expression [-Woverflow]
假设int
您的系统上的 a 大小是 32 位,那么您很可能会导致溢出并且结果i * 16
变为负数。在二进制补码系统中,负值用较高的二进制值表示。
int reps = 256 * 1024 * 1024;
所以reps = 268,435,456
,这是你循环到的值。因此的最大值i
是268,435,455
和268,435,455 * 16 = 4,294,967,280
。
int
32 位可以表示的最大正值是2,147,483,647
(4,294,967,295
对于 an unsigned int
,所以你还没有环绕负数),这意味着结果被解释为负值。
访问负偏移量arr
超出了分配内存的范围,这会导致未定义的行为,幸运的是会出现段错误。