Global array exceeding length returns 0

I'm trying to understand the c++ compiler ;-(
If i define an int array inside a function and i do not initialize the values of the elements, i will get nonsense values like -1080557484. I understand that a globaly defined array [see example], will 'set' every value that is defined by the length of the array will be set to 0. And it does. But when the pointer goes beyond the array length, it keeps showing 0 as ref value, where as one would aspect nonsens...
Could someone sheld some light on this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// pointer to global value array out of range?
#include <iostream>
using namespace std;

int number[3];

int main ()
{
  int * q = number;
  number[0] = 111;

  cout << "global: int number[3], and number[0] initialized as 111, and q = number.\n";
  cout << "print q //number[0] - defined and initiated as 111: \n  " << q << endl;
  cout << "print *q: " << *q << endl;
  q++;
  cout << "q++";
  cout << "print q //number[1] - defined but not initialized: \n  " << q << endl;
  cout << "print *q: " << *q << endl;
  ++q;
  cout << "++q";
  cout << "print q //number[2] - defined but not initialized: \n  " << q << endl;
  cout << "print *q: " << *q << endl;
  q++;
  cout << "q++";
  cout << "print q //number[3] not defined at all: \n  " << q << endl;
  cout << "print *q: " << *q << endl;
  q++;
  cout << "q++";
  cout << "print q //number[4] not defined at all: \n  " << q << endl;
  cout << "print *q: " << *q << endl;

  return 0;
}
But when the pointer goes beyond the array
... you are invoking UB and anything could happen, including your behavior and formatting of your hard drive. Maybe compiler places static storage duraton variables in zeroed-out memory block, maybe you are running into some other array/variable (defined in standard lobrary for example)
... you are invoking UB and anything could happen, including your behavior and formatting of your hard drive. Maybe compiler places static storage duraton variables in zeroed-out memory block, maybe you are running into some other array/variable (defined in standard lobrary for example)

UB Undefined behaviour? formatting of your [actualy my] hard drive...
Now i'am worried even more. Doesn't the compiler cope with that, in this case a simple typing mistake could result in that. And still, why does the compiled program return 0 while the pointer acceeds the length of the array. Also, the same danger should be there if i point to a single var and incrementing the pointer, yes/no?
Last edited on
Doesn't the compiler cope with that, in this case a simple typing mistake could result in that
No it doesn't and cannot. Imagine this:
1
2
3
4
void foo(int* arr, int n)
{
    arr[n] = 0;
}
This function is inside its own compilation unit, compiler does not know who will call it and which values will be passed. So it cannot say if some access is legal or illegal (at least not with c arrays. All C++ containers provide functionality for that).

This is common source of security vulnerabilities: accidental error will not lead to formatting of hard drive (at least it is very unlikely occurence), but some person, who studies compiled code and notices pattern of memory can overwrite, say, return address of function call, giving cotrol to malicious code (which can format your hard drive).

the same danger should be there if i point to a single var en incrementing the pointer, yes/no?
Yes. It has same consequences. Pointers are unsafe: they like a sharp razor — useful tool, but dangerous for those who handles it carelessly.

still, why does the compiled program return 0 while the pointer acceeds the length of the array
Maybe you are running your program in debug mode and debugger zeroes all memory before use, maybe there is another object which has zeroes in its internal representation, who knows? I actually get 1 as number[4]. So, it just happens that way.

Bonus reading:
http://blogs.msdn.com/b/oldnewthing/archive/2014/06/27/10537746.aspx
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
Doesn't the compiler cope with that, in this case a simple typing mistake could result in that.
It might. Undefined behavior means that the compiler is free to generate any code. It might generate a program that deliberately crashes to prevent loss of data, or it might generate one that computes digits of pi. Or it might generate a program that wipes out your computer. All of these are valid alternatives.

And still, why does the compiled program return 0 while the pointer acceeds the length of the array.
Because the behavior is undefined. If you want to know the immediate reason, you'll have to disassemble the generated code to see what the compiler did.

Also, the same danger should be there if i point to a single var and incrementing the pointer, yes/no?
Yes.
> Also, the same danger should be there if i point to a single var and incrementing the pointer, yes/no?

No, there is no danger. The behaviour is well defined.

For purposes of pointer arithmetic and comparison, an object that is not an array element whose address is taken in this way is considered to belong to an array with one element of type T.
[Example:
...
int a;
int* p1 = &a;
int* p2 = p1 + 1; // defined behavior
bool b = p2 > p1; // defined behavior, with value true
—end example]


There would be undefined behaviour if we try to increment the incremented pointer.
Or if we try to access an object through the incremented pointer.
JLBorges wrote:
For purposes of pointer arithmetic and comparison, an object that is not an array element whose address is taken in this way is considered to belong to an array with one element of type T.


Okay, this sheds a new light on the 'problem'. Considering template. It overloads to the types you include. But what is type T? In the code i showed before no template was used, nor type 'T'.

The string was defined globaly: int number[3];
Within main(), one value was initialized: number[0]=111;

Outputting number[3], and more over number[4], should give nonsense value or some error at compile time. The latter doesn't show as the compiler can't figure it out - that i learned so far. But why does the [compiled] program return 0, when it should be pointing to a ref value 'garbage', like value -1080557484.
But why does the [compiled] program return 0, when it should be pointing to a ref value 'garbage', like value -1080557484.
Because the behavior is undefined. If you want to know the immediate reason, you'll have to disassemble the generated code to see what the compiler did.
Garbage is merely data that's meaningless to the reader. You're reading past the end of an array, which is an operation that doesn't make logical sense, so anything you manage to actually read from there can be nothing but garbage. Just because this garbage happens to have the value 0 instead of some random value doesn't mean it's not still garbage.
Topic archived. No new replies allowed.