Why don't I get a segmentation fault when I write beyond the end of an array?

why is this not giving error when I compile?

#include <iostream>
using namespace std;

int main()
{
    int *a = new int[2];
    // int a[2]; // even this is not giving error
    a[0] = 0;
    a[1] = 1;
    a[2] = 2;
    a[3] = 3;
    a[100] = 4;
    int b;

    return 0;
}

can someone explain why this is happening. Thanks in advance.)


Solution 1:

Because undefined behavior == anything can happen. You're unlucky that it doesn't crash, this sort of behavior can potentially hide bugs.

As for a being define twice - that's a bug in the compiler.

Solution 2:

Declaring two variables called a certainly is an error; if your compiler accepts that, then it's broken. I assume you mean that you still don't get an error if you replace one declaration with the other.

Array access is not range-checked. At compile time, the size of an array is often not known, and the language does not require a check even when it is. At run time, a check would degrade performance, which would go against the C++ philosophy of not paying for something you don't need. So access beyond the end of an array gives undefined behaviour, and it's up to the programmer to make sure it doesn't happen.

Sometimes, an invalid access will cause a segmentation fault, but this is not guaranteed. Typically, memory protection is only applied to whole pages of memory, with a typical page size of a few kilobytes. Any access within a page of valid memory will not be caught. There's a good chance that the memory you access contains some other program variable, or part of the call stack, so writing there could affect the program's behaviour in just about any way you can imagine.

If you want to be safe, you could use std::vector, and only access its elements using its at() function. This will check the index, and throw an exception if it's out of range. It will also manage memory allocation for you, fixing the memory leak in your example.