3

I'm a programming and c++ novice. I'd appreciate some help with this.

the following program (in c++) doesn't encounter any problem either in compilation or run-time:

int main()
{
    int b = 5;
    int*a = &b;
    *(a+5) = 6;
    return 0;

}

But according to everything I learned it shouldn't work, because a is a pointer to a single variable. What am I missing here?

Magnus Hoff
  • 21,529
  • 9
  • 63
  • 82
Person1
  • 67
  • 4

4 Answers4

6

Your program should indeed not encounter any problem at compile time. It is all valid code with regards to compilation.

However it will encounter undefined behaviour at runtime as a+5 is not a valid address.

If you want to know why it should compile, you can write code like this:

int func( int * buf, size_t size )
{
    for( size_t i = 0; i < size; ++i )
    {
       *(buf + size) = static_cast<int>(i); // or (int)i in C
    }
}

int main()
{
   int buf[ 6 ];
   func( buf, 6 );
}

In your code a is a pointer to memory. a + 5 means an address 5 "ints" on from where a points. As a was pointed at a single integer b, there are no guarantees about such an address. Interestingly enough, it is well defined to refer to a+1 even though it points to a place in memory that you should not read from or write to. But the pointer itself has some guarantees, i.e. it will be greater than a and if you subtract 1 from it you will get back to a and if you do a ptrdiff between it and a you will get 1. But that is just a special property of "one past the end" which allows programmers to specify memory ranges.

CashCow
  • 30,981
  • 5
  • 61
  • 92
  • I like this answer :) However, it is probably appropriate to explain the difference between undefined behavior and "shouldn't work" to this asker :) – Magnus Hoff Jan 14 '15 at 09:36
  • The behaviour is undefined and depends on the CPU architecture, wrt how it handles the stack. `a+5` is a valid address and there may be no problems with it at all. The `b` memory is on the stack, so `a+5` is five ints higher up the address space than teh address of `b`. If the stack is ascending there will be no problem as this will be unused memory. If it is descending, maybe a big oops. – Evil Dog Pie Jan 14 '15 at 09:37
  • 1
    a+5 is not a a valid address. a+1 is although you can't dereference it. – CashCow Jan 14 '15 at 09:38
  • Thanks. I get it. Thank everyone else for your answers. – Person1 Jan 14 '15 at 09:46
  • All the answers and comments here doesn't take in count the case where 'a+5' is a not allocated memory. – Roee Gavirel Jan 14 '15 at 10:04
  • @RoeeGavirel it's not actually relevant according to the standard, since going past `a+1` is a one-way ride to UB land. – Quentin Jan 14 '15 at 10:07
  • Why is a+1 a valid address? – Shmoopy Jan 14 '15 at 10:19
  • a+1 being a valid address lets you use the single pointer in a function that takes a range, where your range is of size 1. The standard says one past the end is valid. That's why it is. You cannot read or write from it but you can use it as a pointer. – CashCow Jan 14 '15 at 10:21
1

The program do have an undefined behaviour:

int main()
{
    //This cause the loading of the "main" function to allocate memory for variable b
    //It could be in a memory page that was already allocated to the program
    //or in a new allocated page.
    int b = 5;

    //Here a just getting the address of variable b.
    int*a = &b;

    //This is the undefined behavior and can end up in two cases:
    // 1. If (a+5) value is in a memory space that is allocated to the application.
    //    Then no runtime error will happen, and the value will be writing there.
    //    probably dirting some other value, and can cause an undefined behavior later
    //    in the application execution.
    // 2. If (a+5) value is in a memory space that wasn't allocated to the application.
    //    the application will crash
    *(a+5) = 6;
    return 0;

}

Now, since a page size is probably 4096 and b is somewhere within a page, *b+5 is in most cases still be in the same page. If you want to challenge it more change it from 5 to 5000 or higher and the chance for crashes will increase.

Roee Gavirel
  • 18,955
  • 12
  • 67
  • 94
0

Yes it shouldn't work when you access memory space which is not in your process region, but perhaps no one has owned that particular region ((a + 5)) which didn't cause run time illegal memory access or it can. Hence its a UB.

Sunil Bojanapally
  • 12,528
  • 4
  • 33
  • 46
0

Just adding to the existing answers.

The access

*(a+5) = a[5]

So this is the location not allocated by you.

In the case of array say

int a[6];

You have a valid access from a[0] to a[5] where a[5] is the last element of the array and any further access like a[6] will lead to undefined behavior as that location is not allocated by you.

Similarly you just have a integer allocated like

int b=5;

int *a = &b;

a is a pointer pointing to &b i.e address of b.

So the valid access for this is just a[0] which is the only location allocated by you on the stack.

Any other access like a[1] a[2]... and so on will lead to undefined behavior.

The access turns out to be VALID if you have something like

int b[6];
int *a = b;

Now a[5] will give the value of the last element of the array b

Gopi
  • 19,784
  • 4
  • 24
  • 36