ps-aux
ps-aux

Reputation: 12146

Alocating local variables on stack & using pointer arithemtic

I read that in function the local variables are put on stack as they are defined after the parameters has been put there first.

This is mentioned also here

5 .All function arguments are placed on the stack. 6.The instructions inside of the function begin executing. 7.Local variables are pushed onto the stack as they are defined.

So I excpect that if the C++ code is like this:

#include "stdafx.h"
#include <iostream>

int main()
{

    int a = 555;
    int b = 666;
    int *p = &a;

    std::cout << *(p+1);
    return 0;
}

and if integer here has 4 bytes and we call the memory space on stack that contains first 8 bits of int 555 x, then 'moving' another 4 bytes to the top of the stack via *(p+1) we should be looking into memory at address x + 4.

However, the output of this is -858993460 - an that is always like that no matter what value int b has. Evidently its some standard value. Of course I am accessing a memory which I should not as for this is the variable b. It was just an experiment.

How come I neither get the expected value nor an illegal access error?

Where is my assumption wrong?
What could -858993460 represent?

Upvotes: 0

Views: 119

Answers (2)

Manu343726
Manu343726

Reputation: 14174

Your assumptions are true in theory (From the CS point of view).

In practice there is no guarantee to do pointer arithmetic in that way expecting those results.

For example, your asumption "All function arguments are placed on the stack" is not true: The allocation of function argumments is implementation-defined (Depending on the architecture, it could use registers or the stack), and also the compiler is free to allocate local variables in registers if it feels necesary.

Also the asumption "int size is 4 bytes, so adding 4 to the pointer goes to b" is false. The compiler could have added padding between a and b to ensure memory aligment.

The conclusion here is: Don't use low-level tricks, they are implementation-defined. Even if you have to (Regardless of our advises) do it, you have to know how the compiler works and how it generates the code.

Upvotes: 1

sqykly
sqykly

Reputation: 1586

What everyone else has said (i.e. "don't do that") is absolutely true. Don't do that. However, to actually answer your question, p+1 is most likely pointing at either a pointer to the caller's stack frame or the return address itself. The system-maintained stack pointer is decremented when you push something on it. This is implementation dependent, officially speaking, but every stack pointer I've ever seen (this is since the 16-bit era) has been like this. Thus, if as you say, local variables are pushed on the stack as they are initialized, &a should == &b + 1.

Perhaps an illustration is in order. Suppose I compile your code for 32 bit x86 with no optimizations, and the stack pointer esp is 20 (this is unlikely, for the record) before I call your function. This is what memory looks like right before the line where you invoke cout:

4: 12 (value of p)
8: 666 (value of b)
12: 555 (value of a)
16: -858993460 (return address)

p+1, since p is an int*, is 16. The memory at this location isn't read protected because it's needed to return to the calling function.

Note that this answer is academic; it's possible that the compiler's optimizations or differences between processors caused the unexpected result. However, I would not expect p+1 to == &b on any processor architecture with any calling convention I've ever seen because the stack usually grows downward.

Upvotes: 2

Related Questions