C + + memory distribution and variable initialization order __c++

Source: Internet
Author: User


On the stack, out of the stack, stack top stack, such as the analysis see

Analysis of Stack stack process of function call

The following continues the analysis of C + + memory distributions.



Although 0x10 is a bit larger than the 4 addresses needed for a variable, the 0x10 should be the minimum unit required. If you want to use the space just is its integer times, in fact, is not wasting a penny stack space, the bottom do an array, proving that the stack space is exactly the size of all non-static variables occupy space.

Here you can ignore the statement of Hello, it is not in the stack space, will be analyzed later.

   X6       #include <stdio.h>                                       x
   x7       int main () {                                             x
   x9               static int hello;                               x 
b+>x11              int array[100] = {7,4,1};                       X
   x16 return              0;                                       X
   x17      

Below is the assembly code: more complex than ordinary variables, more use of some registers, more than a few push, pop operation, there are rep instructions.

   x0x8048394 <main> push%ebp x x0x8048395 <main+1> mov %ESP,%EBP x x0x8048397 <main+3> push%edi x x0x8048398 &L              t;main+4> push%EBX x x0x8048399 <main+5> Sub $0x190,%esp              X b+>x0x804839f <main+11> lea-0x198 (%EBP),%ebx x x0x80483a5 <main+17> mov $0x0,%eax x X0X80483AA <main+22> mov $0x64,%edx x 100 variables (there should also be a flag type size is 4 things bar) x0x80483af <main+27> mov%ebx,%edi x x0x80483b1 <ma         In+29> mov%edx,%ecx x x0x80483b3 <main+31> Rep stos%eax,%es: (%edi)
   X x0x80483b5 <main+33> movl $0x7,-0x198 (%EBP) x initialized three numbers. X0X80483BF <main+43> MOVL $0x4,-0x194 (%EBP) x x0x80483c9 <main+53> movl $0x1,-0x190 (%EBP) x x0x80483d3 <main +63> mov $0x0,%eax x x0x80483d8 <main+68> Add $0x190,%esp x0x                             80483de <main+74> pop%ebx x x0x80483df <main+75> pop%edi x x0x80483e0 <main+76> pop%ebp x x0x80483e1 <main +77> ret x x

Below is the stack space size. Subtract, 0x190, equals 400bytes, just 100 int.

(gdb) Print $esp
$ = (void *) 0xbffff480
(gdb) print $ebp
$ = (void *) 0xbffff618

As we all know, adding static extends the life cycle of the variable to the end of the program, or the "static variable address is not the same."

Indeed, the address has changed and the static variable is not in the stack.

int main () {
        static int hello;
        int top;
        return 0;
}
Address, top is on the stack, and Hello is not

(gdb) Print &top
$ = (int *) 0xbffff614
(gdb) print &hello
$ = (int *) 0x8049614
Stack size is 0x10
(gdb) Print $esp
$ = (void *) 0xbffff608
(gdb) print $ebp
$ = (void *) 0xbffff618
Remove the declaration of the int type, leaving only a static variable declaration, you will find an interesting phenomenon that is, even the statement is "optimized" gone, not in the main () function inside, does not execute in the main () function means what. The lifecycle is not only extended back to the end of the program, it is also extended forward, which is initialized outside of main and earlier. So if I do it in the main () function before the static variable declaration statement, I'm not allowed. It may be syntactically masking, but it should be done in the order in which they are run. This sentence translates into code, and it's like this:
#include <stdio.h>
int main () {
        Hello = 4;
        static int Hello;
        return 0;
}
Even beginners think it's impossible, but if I do it in a different way.
#include <stdio.h>
static int hello;
int main () {
        Hello = 4;
        return 0;
}
So everyone will agree. But I think that these two are essentially equivalent, but the compiler at the agricultural level to shield this operation, may be too wonderful to understand. Personally, I think so. Do not have to try, do compile but .... Replace with a compiled version run once:
   x0x8048394 <main>                Push   %ebp                     x
   x0x8048395 <main+1>              mov    %esp,%ebp                x
B + >x0x8048397 <main+3>              movl   $0x4,0x8049614           x
   x0x80483a1 <main+13>             mov    $0x0,%eax                x
   x0x80483a6 <main+18>             pop    %ebp                     x
   x0x80483a7 <main+19>             RET                             x

Main declaration must be invisible, directly used for a while, if there is no that assignment statement, main internal what life you can not see, the direct end.
I thought of another way, because after compiling I could look at the address, sometimes (perhaps) not to do "variable list" (that is, all variables and the number of integrated) level of change, in fact, the address is similar, so you can try to compile the run, see the address, and then forcibly extracted variables, C language strong. (c language is not like this play well-_-) This is my idea:

#include <stdio.h>
int main () {
        int *ptr = 0x8049614;
        printf ("%d\n", *ptr);
        static int hello = m;
        return 0;
}
Print *ptr = 0 (expected 100) did not succeed, but there is hope, because this time the compilation address has changed:

Again:
#include <stdio.h>
//static int hello = m;
int main () {

        int *ptr = 0x8049578;
        printf ("%d\n", *ptr);
        static int hello = m;

        return 0;
}
But the nasty is changed again .... This (global variable area). What do you call it? Address allocation is very dynamic, not as stable as the stack address.
Be sure to catch it, try 664.
I finally got caught.
The static variable Hello declaration and definition are all in 13 lines, but I was in line 12 in advance and printed out. Come on, let's do a normal run.


However, the eggs, in reality, which people run the end to see the results, hard to write the address, I do not know how to play can be used where.
This example is only for the proof:1. The storage area of the static variable is not in the stack, and it is not as stable as the address rules of the stack, but it can be stabilized to some extent, so it can be grasped. 2. Encounter that "static", this statement is defined and put on the outside of main no difference, the execution of the code is equal to the implementation of the program before the execution, calculate initialization bar. 3. Therefore, regardless of the static variable declaration, its lifecycle is always throughout the program. 4. Clearly very early declaration of the definition, the reason why you can not directly to extract the value of static variables, should only be set up by the compiler rules, to avoid some unnecessary human error it. 5. Static is called statically, static stillness is where. Where the dynamic moves again. Dynamic of course is moving in you run it only results, do not run without. Although the stack will be in advance (run function body before) allocate enough space, but the definition of the minimum variable value is not, and static, is a long time to define the value of the finished, so called static. (So there is a good reason to suspect that the compiler is based on the variable type and number, the assumption is called "variable list" to allocate stack space, who told me to learn slag not how to learn the principle of compiling, can only guess first) 6. Don't imitate


Extended training: Add two-tier functions.


please allow me to review C + +:Whether the C + + class static members will be different. is initialized very early, or starts with an object running the function. If it is a defined form, for example, the static int i = 1 instead of the static int i; First, the first form, ISO C + + is not allowed (error: ISO C + + does not allow the initialization of very static members within the class). Second, the static member variable I of A is not allowed to be accessed using the A::i form.

"Strange" discovery:When you declare multiple class objects consecutively with a class, the class object behind is placed in a different place by some sort of optimization mechanism (heap. Global static area. )
The specific process is as follows: First compile: F f,f2;//object on stack
Second compilation:
F f,f2,f3,f4,f5,f6,f7,f8,f9;//only F and F2 in stack//NOTE: At this time ESP and EBP unchanged, the stack does not expand, is out of some kind of "lazy" or "disdain."
Compile the third time:
F F,f2,f3,f4;
F f5,f6,f7,f8,f9;//objects are on the stack
Compile for the fourth time:
F f,f2,f3,f4,f5,f6,f7,f8,f9;//all objects are on the stack.

First, the elimination of human error, although allocating the heap when f *PF = f ();//print &AMP;PF pointer address on the stack, the print PF pointer points to the object in the heap. But here is not the pointer, the entity ...

The compiler did some sort of optimization, and the distinction between the optimizations was definitely not code-use, no F2, no use, and the same as F on the stack. But

My summary is that this object variable last had an address, this time there is, because only F f,f2;//led to F2 in the stack, the other F3 to F8 are later appended, compiler because of the habit, leaving the F2 on the stack and the others throwing aside. This time, too, because the f4,f5 have a stack address when split into two statements, so when merging back, the compiler, out of habit, continues to put them on the stack. So, the compiler is with memory (caching).

But then again, when you declare too many object variables, why are they thrown in another position? This is "put the undeclared variable in the static variable area".
And if E e,e2;//suddenly turn into e e,e2,e3,e33,e333,e3333,e33333,e333333,e3333333,e33333333;//and then compile
As a result, all objects are also in the stack, the randomness is too strong, so no longer entangled with the compiler's case characteristics. Waste of time.
=============================================================================================================== ======== 20160324: Add a reference to the function body and code block on the stack, stack and stack frame, this article and the front of a function call on the blog has been written very clearly (or may not be clear, two overlap, the classification of Chaos ~ ~ ~ ~ ~) in short, on the function of local variables, Because the current stack frame is present, the external variable is completely shielded at this time, and the local variable cannot live outside. But the code block is a special case (just from the point of view): The code block can declare the "local" variable, and the "local" variable changes will not affect the previous layer of the "this" variable, said disorderly, on the code:
#include <stdio.h>
int main ()
{
        int i = 0;
        {
                int j = 1;
                i = 1;
                printf ("i:%d\n", I);
                int i = 2;
                printf ("Inside of block:i:%d\n", I);
                printf ("j:%d\n", j);
        }
        printf ("Outside of block:i:%d\n", I);

}

The print result of I is 1,2,1. Here I is able to "repeat the statement", and the modification of the local I of the declaration does not affect the external. Some people may be somewhat puzzled by the concept of the surface. This seems to be part of the code block and the local part of the function body what is the difference.
First of all, if you do not repeat the statement, the changes in the code block, the external is all effective, this point through the for loop, such as the block of code can be experienced. So if you repeat the statement, what is the difference? In fact, this "repeat statement" is just a variable of the new declaration, you assume it as K, so any changes to K, of course, will not affect I.

Other mechanisms, coordination work, are the compiler itself mapped well, do not care.
However, there are shortcomings in doing so, you have to occupy the stack space, it is not you really go to briefly cover the original variable after the recovery, there is no memory for memory how it may cover the recovery. Such benefits may be the one you use for (int i = 0;condition;modify i); This kind of thing, avoid mutual interference bar. So, if there is a demand, the local simply or change a name (k) bar, essentially the same as to avoid the reduction of readability.

=============================================================================================================== ======= about the main function of those before the Assembly, I do not understand, have time to explore, want to know the initialization of static variables, various classes, as well as virtual function table initialization process.





Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.