Why the addresses of local variables can be differ

2019-06-16 15:41发布

I've asked Google and did some research on StackOverflow. My question is that when I enter the main() function in a C++ program and declare the very first variable, why is it that the address of this variable can vary upon different executions? Please see my example program below:

#include <iostream>

int main() {
    int *a = new int;
    int *b = new int;

    std::cout << "address: " << a << " " << b << std::endl;
    std::cout << "address of locals: " << &a << " " << &b << std::endl;
    return 0;
}

Result on execution 1:

address: 0xa32010 0xa32030
address of locals: 0x7fff10de2cf0 0x7fff10de2cf8

Result on execution 2:

address: 0x1668010 0x1668030
address of locals: 0x7ffc252ccd90 0x7ffc252ccd98

Result on execution 3:

address: 0x10e0010 0x10e0030
address of locals: 0x7ffd3d2cf7f0 0x7ffd3d2cf7f8

As you can see, I get different results upon different executions. The first line of the output corresponding to the address of the allocated memory, which should happen in the heap – if they are assigned different addresses every time, it kinda make sense to me. However, even when I print the addresses of local variables – corresponding to the second line – the results are still different.

At first glance, I was thinking it's because the program is printing a physical memory address, but this post, Virtual Memory or Physical Memory, disproves my initial thought. Is there any reason that, given the programs’ execution is "the same," with no threading, no user inputs, etc, that there are still memory allocations with different addresses?

Testing environment:

  • Linux 14.04
  • Mac OS X 10.10

1条回答
The star\"
2楼-- · 2019-06-16 16:29

When allocating on the heap (using the new operator or malloc() and friends), your program has to ask the OS to allocate your heap memory. Lots of behind-the-scenes stuff happens in the OS memory manager (the implementation details of which are mostly above my pay-grade: garbage collection, consolidation of reclaimed memory, etc) and it is a good thing to not have to think about it.

Local variables are allocated on the stack. Traditionally, stack allocation would be repeatable, but this has changed in recent years. Address space layout randomization (ASR) is a relatively recent innovation in OS memory management, which deliberately makes memory addresses in stack allocations (such as those you have observed) as non-deterministic as possible at runtime. It’s a security feature: this keeps bad actors from exploiting heap buffer overflows, because if the ASLR implementation is entropic enough, who knows what’s going to be there at the end of the overflowing buffer?

The price you pay for this and other memory-management features is control. Betting on the addresses of allocations on a modern (non-embedded) platform is like playing Powerball: possibly an amusing distraction but not a workable plan for the future. If your code is running on an AVR-ISA platform or somesuch, maybe the odds are closer enough to Blackjack such that someone might be enticed to play to win (so to speak).

Either way I am not a gambling man, personally – as I often say, gentlemen prefer stack allocation. But that is basically why you are getting those results.

Thanks to @T.C. for the link and @SergeyA for the suggestion.

查看更多
登录 后发表回答