分段错误:arr [(i * 16)%arrLen] vs arr [i%arrLen]

时间:2012-09-26 10:59:20

标签: c

another question中处理我的作业,更多细节。如果我使用

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

vs

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

为什么呢? Full source 请参阅第31行。为什么?我模数组的长度,所以应该没问题?

3 个答案:

答案 0 :(得分:5)

i * 16可以溢出到有符号整数的负范围内。当你取一个负整数的模数时,你可以得到一个负余数,这将使你的数组​​下标为负数,并导致在数组的已分配内存之外的访问,有时会崩溃。

答案 1 :(得分:1)

假设系统上int的大小为32位,则可能导致溢出,i * 16的结果变为负值。在二进制补码系统中,负值用更高的二进制值表示。

int reps = 256 * 1024 * 1024;

所以reps = 268,435,456,这是你要循环的价值。因此i的最大价值是268,435,455268,435,455 * 16 = 4,294,967,280

32位int可以表示的最大正值为2,147,483,6474,294,967,295 unsigned int,因此您尚未包含负数,)这意味着结果被解释为负值。

arr访问负偏移超出了已分配内存的范围,这会导致未定义的行为,幸运的是会出现seg错误。

答案 2 :(得分:1)

查看完整资料来源:

  1. 您应该检查malloc的返回以确保您能够获得该内存
  2. 你应该释放记忆,你有泄漏
  3. 你的arr数组中的内存是未初始化的,你分配它但不要将它设置为任何东西,所以你(很可能)得到一个大的负数。这可以通过memset(arr,0,arrLen);
  4. 完成
  5. malloc(arrLen * sizeof(int))但是arrLen是使用/sizeof(int)创建的,所以你取消了那里的工作......
  6. 关于你的seg错误,正如其他人已经声明你的阵列溢出。你已经创建了一个int数组。然后你从0循环到reps(268,435,456),这是int的最大大小。当你试图将它乘以16时,你会溢出并产生负偏移。

    尝试将16乘以reps的初始化:

    int reps = 256 * 1024 * 1024 * 16;
    

    您的编译器应该发出警告,让您知道这一点:

    warning: integer overflow in expression [-Woverflow]