0

As an example here, I am creating a 2d array of doubles of 1000 by 2 and filling out every spot in the 2d array with 222222.0

What's really weird is that if I go for example to array[999][1000], I get 222222.0

But if I make my array size say only 100 by 2, this doesn't happen and if I try array[99][10], I just get 0.0

What's going on? Why do I get this "leakage"?

int N = 1000;
int dimension = 2;

double** nums = malloc(sizeof(double*) * N);
for(int i = 0; i < N; i++)
    nums[i] = malloc(sizeof(double) * dimension);

for (int k = 0; k < dimension; k++)
    for (int i = 0; i < N; i++)
        nums[i][k] = 222222;

printf("%f\n", nums[99][1000]);

222222.000000

Huh?

jww
  • 97,681
  • 90
  • 411
  • 885
jeremy radcliff
  • 1,049
  • 3
  • 11
  • 27
  • 2
    C have no bounds checking. At all, not even for normal arrays. Going out of bounds leads to *undefined behavior* and that's it. – Some programmer dude Feb 18 '17 at 18:28
  • @Someprogrammerdude Yes but clearly it's no coincidence that the number I find out of bounds is 222222.0. How does that happen? Am I messing up the bounds when I assign 222222.0 to every element in my array. How do I find this very specific number at column 1000 when I only assigned it up to the 2nd column? – jeremy radcliff Feb 18 '17 at 18:29
  • 2
    With a dynamically allocated "2d" array like yours, yes it *is* a coincidence. Undefined behavior is, by its very definition, undefined. You can't trust *anything* that is happening in a program with it. I think the C specification even says that a program with undefined behavior is *ill-formed*, that is invalid. – Some programmer dude Feb 18 '17 at 18:32
  • 1
    You have a dynamically allocated array of pointers, to (separately) dynamically allocated arrays of `double`... those arrays of `double` are not necessarily allocated contiguously, so your out of bounds access could very well reach into one of the other sub-arrays (or not -- it's undefined behaviour). – Dmitri Feb 18 '17 at 18:33
  • 2
    "Undefined" means the C language provides *no explanation whatever* for what you get by evaluating `nums[99][1000]`. It also means that you cannot rely on it being the same from one implementatoin to another, or even from one run of the program to another. Possibly your particular implementation provides more guarantees, but more likely not. It's not much useful to speculate on how the particular manifestation of undefined behavior comes to pass. – John Bollinger Feb 18 '17 at 18:33
  • @JohnBollinger Thanks for all the comments. I guess i really never understood the extent to which undefined behavior can have an impact on programs. – jeremy radcliff Feb 18 '17 at 19:17
  • 1
    Possible duplicate of [Does "Undefined Behavior" really permit \*anything\* to happen?](http://stackoverflow.com/questions/32132574/does-undefined-behavior-really-permit-anything-to-happen) – Bo Persson Feb 18 '17 at 21:55
  • You might try printing out `nums[i]` for various i. What's probably happening is that malloc is allocating on a 32- or 64-byte boundary, then you assign values to the first 16 bytes. Then, `nums[99][1000]` winds up being 8000 bytes past `nums[99][0]` and there's a 25% or 50% chance that it refers to values that you assigned. – Mark Plotnick Feb 18 '17 at 22:33
  • @Some Programmer Dude - He may be able to use Clang and GCC's Bounds Sanitizer with `-fsanitize=bounds-strict`. I believe it takes advantage of processor features to perform the bounds checking, so runtime penalties are minimized. But like you said, its not part of the C language. – jww Feb 19 '17 at 21:00

0 Answers0