1

Working on my assignment, more details in another question. If I use

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

vs

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

Why? Full source see line 31. Why? I modulus the array length so it should be OK?

Community
  • 1
  • 1
Jiew Meng
  • 84,767
  • 185
  • 495
  • 805

3 Answers3

5

i * 16 can overflow into the negative range of signed integers. When you take modulo of a negative integer, you can get a negative remainder and that'll make your array subscript negative and result in an access outside of the array's allocated memory and sometimes a crash.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
1

Assuming the size of an int on your system is 32-bits, chances are you're causing an overflow and the result of i * 16 is becoming negative. In a two's complement system, negative values are represented with a higher binary value.

int reps = 256 * 1024 * 1024;

So reps = 268,435,456, which is the value you're looping up until. The greatest value of i is therefore 268,435,455 and 268,435,455 * 16 = 4,294,967,280.

The largest positive value a 32-bit int can represent is 2,147,483,647 (4,294,967,295 for an unsigned int, so you haven't wrapped around the negatives yet), which means that result is being interpreted as a negative value.

Accessing a negative offset from arr is out of the bounds of your allocated memory, which causes undefined behaviour and fortunately a seg fault.

AusCBloke
  • 18,014
  • 6
  • 40
  • 44
1

Looking at your full source:

  1. You should be checking the return of malloc to make sure you were able to get that memory
  2. You should be freeing the memory, you have a leak
  3. The memory inside your arr array is uninitialized, you allocate it but don't set it to anything so you're getting (most likely) a large negitive number. This can be done by memset(arr,0,arrLen);
  4. You malloc(arrLen * sizeof(int)) however arrLen is created with a /sizeof(int), so you're canceling your work there...

Regarding your seg fault, as others have stated your overflowing your array. You've created an array of ints. The then you're looping from 0 to reps (268,435,456) which is the max size of an int. When you try to multiply that by 16 you're overflowing and creating a negative offset.

Try multiplying the 16 into the initialization of reps:

int reps = 256 * 1024 * 1024 * 16;

Your compiler should throw a warning letting you know this exact thing:

warning: integer overflow in expression [-Woverflow]
Mike
  • 47,263
  • 29
  • 113
  • 177
  • hmm I am not getting any errors, I'm new to C. I think I need a flag? Regarding (3) how can I zero or initialize my array? – Jiew Meng Sep 26 '12 at 12:47
  • Well it's not an error, it's a warning, and your not going to see it unless you make the `* 16;` I pointed out. What compiler/command are you using to build? I updated 3 with the code (note I only used arrLen for the length because of point 4). – Mike Sep 26 '12 at 12:50
  • RE: (4), actually, I think malloc is right tho? I am allocating `targetSizesInKB[sizeIndex] * 1024` bytes? – Jiew Meng Sep 26 '12 at 13:06