1

处理我的任务,另一个问题的更多细节。如果我使用

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

对比

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

为什么?完整来源见第 31 行。为什么?我对数组长度取模,所以应该没问题?

4

3 回答 3

5

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

于 2012-09-26T11:07:08.433 回答
1

查看您的完整来源:

  1. 您应该检查 malloc 的返回以确保您能够获得该内存
  2. 你应该释放内存,你有泄漏
  3. 您的 arr 数组中的内存未初始化,您分配它但不将其设置为任何内容,因此您(很可能)得到一个很大的负数。这可以通过memset(arr,0,arrLen);
  4. 但是,您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]
于 2012-09-26T11:55:04.657 回答
1

假设int您的系统上的 a 大小是 32 位,那么您很可能会导致溢出并且结果i * 16变为负数。在二进制补码系统中,负值用较高的二进制值表示。

int reps = 256 * 1024 * 1024;

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

int32 位可以表示的最大正值是2,147,483,6474,294,967,295对于 an unsigned int,所以你还没有环绕负数),这意味着结果被解释为负值。

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

于 2012-09-26T11:10:42.693 回答