A detailed description of the C + + heap, stack and static data area

Source: Internet
Author: User
Tags class definition function prototype modifier modifiers stack pop

Turn from: https://www.cnblogs.com/hanyonglu/archive/2011/04/12/2014212.html make slight changes

This article describes the heap, stack, and static data areas in C + +. five large memory partitions

In C + +, memory is divided into 5 extents, namely heap, stack, free storage, global/static storage, and constant storage. The following are respectively introduced:

Stacks, which are the stores of variables that are allocated by the compiler when needed, and automatically purged when not needed. The variables inside are usually local variables, function parameters, and so on.

Heap, which is the memory blocks allocated by new, their release compiler does not go to the tube, by our application to control, generally a new will correspond to a delete. If the programmer does not release it, the operating system will automatically recycle after the program finishes.

The free storage area, which is the memory blocks allocated by malloc, is very similar to the heap, but it ends up living with no.

Global/static storage, global variables and static variables are allocated in the same piece of memory, in the previous C language, the global variables are divided into initialization and uninitialized, in C + + There is no such distinction, they occupy the same chunk of memory (uninitialized variables are initialized to 0 or empty string, C also same).

Constant storage, which is a special piece of storage, they are stored in constant, not allowed to modify (of course, you have to pass the improper means can also be modified, and many methods).

Explicitly differentiate heaps from stacks:

On BBS, heap and stack of the problem, seems to be an eternal topic, this shows that the beginner is often confused, so I decided to take his first surgery.

First, let's give an example:

void F () {int* p=new int[5];}

The above short sentence contains the heap and stack, see new, we should first think that we have allocated a heap of memory, then pointer p? He allocates a stack of memory, so the meaning of this sentence is: In the stack memory is stored in a pointer to a heap of memory p. The program will first determine the size of the memory allocated in the heap, then call operator new to allocate memory, and then return the first address of the memory, put in the stack, his assembly code under VC6 is as follows:

00401028 Push 14h0040102a call operator new (00401060) 0040102F add esp,400401032 mov dword ptr [ebp-8],eax00401035 mov eax , DWORD ptr [ebp-8]00401038 mov dword ptr [Ebp-4],eax

Here, we do not release the memory for the sake of simplicity, then how to release it? Is it delete p? Oh, wrong, should be delete []p, this is to tell the compiler: I delete an array, VC6 will be based on the corresponding cookie information to do the work of releasing memory.

Well, let's go back to our topic: What's the difference between heaps and stacks?

  The main differences are from the following points:

1, different management methods;

2, the space size is different;

3, can produce different fragments;

4, the growth direction is different;

5, the distribution method is different;

6, the allocation efficiency is different;

Management mode: For the stack, is automatically managed by the compiler, without our manual control, for the heap, the release of work by the programmer control, easy to produce memory leak.

Space size: Generally speaking, in 32-bit system, heap memory can reach 4G space, from this point of view heap memory is almost no limit. But for the stack, generally there is a certain amount of space, for example, under the VC6, the default stack space is 1M (as if it is not clear). Of course, we can modify:

Open the project and proceed to the following menu: Project->setting->link, select output in category, then set the maximum and commit of the stack in the reserve.

Note: The reserve minimum value of 4byte;commit is reserved in the virtual memory of the page file, it is set to a large size stack will open up a larger value, may increase the memory overhead and startup time.

Fragmentation problem: For the heap, frequent new/delete is bound to cause memory space discontinuity, resulting in a large number of fragments, so that program efficiency is reduced. For the stack, there is no problem, because the stack is advanced out of the queue, they are so one by one correspondence, so that there will never be a memory block from the middle of the stack pop-up, before he pops up, in the back of his upper stack content has been ejected, detailed can refer to the data structure, here we are no longer one by one discussed.

Growth direction: For the heap, the direction of growth is upward, that is, to the memory address of the direction of increase, for the stack, its growth direction is downward, is to reduce the memory address direction of growth.

Allocation method: The heap is dynamically allocated and there are no statically allocated heaps. Stacks are allocated in 2 ways: static allocation and dynamic allocation. Static allocations are done by the compiler, such as the allocation of local variables. The dynamic allocation is assigned by the ALLOCA function, but the dynamic allocation of the stack is different from the heap, and his dynamic allocation is released by the compiler without our manual implementation.

Allocation efficiency: The stack is the data structure provided by the machine system, the computer will support the stack at the bottom: allocate the address of the special register storage stack, the stack stack has a special instruction execution, which determines the efficiency of the stack is high. The heap is provided by C + + function library, its mechanism is very complex, for example, in order to allocate a piece of memory, the library function will follow a certain algorithm (the specific algorithm can refer to the data structure/operating system) in the heap memory to search for available enough space, if there is not enough space (possibly due to too much memory fragmentation), It is possible to invoke the system function to increase the memory space of the program data segment, so that there is a chance to divide the memory in sufficient size and then return. Obviously, the heap is much less efficient than the stack.

  

From here we can see that heap and stack, due to the use of a large number of new/delete, is prone to large amounts of memory fragmentation, because there is no dedicated system support, inefficient, due to the possibility of triggering user-state and nuclear mentality of the switch, memory applications, the cost becomes more expensive. So the stack is the most widely used in the program, even if the call of the function is done by the stack, the parameters in the function call, the return address, the EBP and the local variables are all stored in a stack. So, we recommend that you try to use stacks instead of heaps.

Although the stack has so many advantages, it is not so flexible compared to the heap, sometimes allocating a lot of memory space, or heap better.

Whether it is a heap or stack, to prevent the occurrence of cross-border phenomenon (unless you deliberately make it out of bounds), because the result of the cross-border is either a program crash, or destroy the program heap, stack structure, produce unexpected results, even in the course of your program, did not occur above the problem, you still have to be careful, Maybe when it's going to blow up, then debug is pretty hard:)

By the way, one more thing, if someone put the stack together said, it means stack, not a heap, hehe, clear?

Static used to control the storage and visibility of variables

A variable defined inside a function, when the program executes to its definition, the compiler allocates space on the stack, and the space allocated by the function on the stack is freed at the end of the function execution, creating a problem: What if you want to save the value of this variable in a function to the next call? The easiest way to think of is to define a global variable, but there are many drawbacks to defining a global variable, and the most obvious disadvantage is that it destroys the scope of access to the variable (the variable defined in this function is not only controlled by this function).

A data object is required to serve the entire class rather than an object, while at the same time trying not to break the encapsulation of the class, which requires that the member be hidden inside the class and not visible externally.

The internal mechanism of static:

A static data member must exist at the beginning of a program run. Because a function is called in a program run, a static data member cannot allocate space and initialization within any function.

In this way, its spatial allocation has three possible places, one is the header file as the outer interface of the class, there is the class declaration, and the second is the inner implementation of the class definition, there is the member function definition of the class, and the third is the global data declaration and definition in front of the main () function of the application.

Static data members are actually allocated space, so they cannot be defined in the declaration of a class (only data members can be declared). A class declaration declares only "dimensions and specifications" of a class and does not actually allocate memory, so it is wrong to write a definition in a class declaration. It also cannot be defined externally in the header file for the class declaration, because that would cause duplicate definitions in multiple source files that use the class.

  

Static is introduced to tell the compiler that the variables are stored in the program's static store rather than on the stack, and that static data members are initialized sequentially in the order in which they are defined, noting that when static members are nested, the nested members are guaranteed to be initialized. The order of elimination is the inverse order of the initialization.

The advantages of static:

Can save memory because it is public to all objects, so for multiple objects, static data members are stored only one place for all objects to be shared. The value of a static data member is the same for each object, but its value can be updated. As long as the value of the static data member is updated once, it is guaranteed that all objects access the same value after the update, which can improve time efficiency.

When you reference a static data member, the following format is used:

< class name >::< static member name >

If the access permission for a static data member is allowed (that is, a member of public), the static data member can be referenced in the program in the format described above.

Ps:

(1) A static member function of a class is an object of the entire class rather than a class, so it does not have the this pointer, which causes it to access only the static data and static member functions of the class.

(2) A static member function cannot be defined as a virtual function.

(3) because the static member is declared in the class, the operation is outside, so it takes the address operation, it is somewhat special, the variable address is a pointer to its data type, the function address type is a "nonmember function pointer".

(4) Since the static member function does not have this pointer, it is almost identical to the nonmember function, resulting in an unexpected benefit: being a callback function allows us to combine the C + + and c-based X window systems, It is also successfully applied to the thread function.

(5) Static does not increase the space-time overhead of the program, but she also shortens the subclass's access time to the static members of the parent class, saving the memory space of the child class.

(6) static data members in the < definition or description > before adding the keyword static.

(7) A static data member is stored statically, so it must be initialized.

(8) Static member initialization differs from general data member initialization:

Initialization is performed outside of the class body, and the front is not static, so as not to be confused with the general static variables or objects;

Initialization without the access control of the member Private,public and so on;

The scope operator is used when initializing to indicate the class to which it belongs;

So we derive the format of the static data member initialization:

< data type >< class name >::< static data member name >=< value >

(9) To prevent the effect of the parent class, you can define a static variable in the subclass that is the same as the parent class to mask the effect of the parent class. Here's one thing to note: we say that static members are shared by the parent and subclass, but we have statically defined static members, does that cause errors? No, our compiler uses a neat trick: name-mangling is used to generate unique flags.

--------------------------------------------------------------------------------------------------------------- ----------------------------

  

Storage categories for C-language variables

The storage space that the user uses in memory is divided into code area and data area two parts. Variables are stored in the data area, and the data area can be divided into static storage and dynamic storage area.

Static storage is the way that a variable is allocated a fixed amount of storage space while the program is running. If the global variable is stored in a static storage area, the program runs and allocates space, and the program runs out of release.

Dynamic storage is the way in which storage space is dynamically allocated when the program is running, based on actual needs. If the form parameter is stored in the dynamic store, the space is allocated when the function is called, and the call completes the release.

Variables for static storage can be initialized at compile time, with the default initial value being O or null character. A variable that is stored dynamically is an indeterminate value if it is not assigned an initial value.

In C, the specific storage categories are automatic (auto), register (register), static (static), and external (extern) four. static storage classes and external storage class variables are stored in the static storage area, and the automatic storage class variables are stored in the dynamic store, and register storage classes are sent directly to the registers.

  

Variable storage class definition method:
Storage class type variable table;
For example:
(1) a,b,c Automatic storage class variable for integer type:
auto int a,b,c;
(2) x, Y, z is a static storage class variable of double type:
Static double x, Y, Z;

1. What are the storage types of variables?
The storage type of the variable is indicated by the storage type designator. The storage type designator can be one of the following class key words:
Auto
Register
extern
Static

The following is a detailed explanation:
The Auto storage class designator--used to describe a variable with local scope, which indicates that the variable has a local (automatic) generation period, but is used very little because it is the default storage class designator for all local scope variable descriptions. Note that all variables defined inside the function are local variables, and the variables defined inside the function are scoped only inside the function. Its lifetime is the time the function runs, and the local variable disappears as soon as it leaves the function or the function terminates.


Register storage Class designator-when this specifier is declared, the compiler will allocate as much as possible to the variable as a storage unit for the variable in the CPU, to speed up the operation. Note that the registers are different from the memory. Registers generally within the CPU, and memory generally refers to external (such as memory), the internal CPU registers its operation speed is very high. When the register is allocated, an external memory is automatically allocated. Its function is equivalent to auto, and can only be used for parameter descriptions of local variables and functions.


Static storage class designator--Indicates that the variable has a static generation period. The characteristic of a static variable is that after it leaves its scope, its value does not disappear.


After returning to the scope, you can continue to use the value of this static variable.


Example: Counting the number of calls to a function using a static variable

int ();    /* Function prototype description */void Main () {int a=0; a=two ();/*a value equals 1*/a=two ()/*a value equals 2*/a=two ();/*a value equals 3*/}int () {static int b=0; /* Defines a local static variable */b; return b; }

If it's not a static variable, it's not going to work.

The value of variable A is always 1, because in function one (), the variable B is not a static variable, its value disappears as it leaves the function, and it is re-assigned a value of 0 when it returns to the function.

extern storage class designator-commonly used in engineering files. In a project file because there are multiple program files, when a variable is defined in a program file, a duplicate definition of the variable will occur if it is defined in another program file. Use the extern storage type designator to indicate that the variable is already defined outside the file. The scope of the extern variable is the entire program.

2. Where are the variables stored in memory?

1) variables can be stored in different places of memory, depending on their generation period. Variables defined in the upper part of the function (global variables or static external variables) and static variables defined inside the function, whose lifetime is the whole process of running the program. These variables are stored in the data Segment. A data segment is a fixed amount of space in memory for these variables, which is divided into two parts, one for initializing variables, and the other to holding uninitialized variables.

2) The generation period of the auto variable defined inside the function (a variable not defined with the keyword static) starts when the program starts executing its block code, until the program leaves the program block. A variable that is a function parameter exists only during the call to the function. These variables are stored in the stack. A stack is a piece of space in memory that starts small and gradually becomes larger automatically until a predefined boundary is reached.

3) When assigning an address space to a pointer using a function such as malloc, the allocated memory block is in a memory space called the heap. The heap starts small, but it grows when you call a memory allocation function such as malloc or Clloc. A heap can share a memory segment with a data segment or stack, or it can have its own segment of memory, depending entirely on the compilation options and operating system. Like stacks, heaps also have a growth limit, and the rules that determine this boundary are the same as the stacks.

--------------------------------------------------------------------------------------------------------------- --------------------------------------------------

  Scope and storage type of C-language variables
I. Scope and lifetime


There are three types of identifier scopes for C programs: local, Global, and file. The scope of an identifier determines which statements in the program can use it, in other words, the visibility of identifiers in other parts of the program. Typically, the scope of an identifier is implicitly described by its location in the program.

  

1. Local scope

The variables in the previous examples are local scopes, which are declared inside the function and cannot be accessed by the code of the other functions. The scope of the formal parameters of a function is also local, and their scope is limited to the block of statements used inside the function.

void add (int);          Main ()          {              int num=5;              Add (num);              printf ("%d\n", num);       /* Output 5*/          }          void Add (int num)          {              num++;              printf ("%d\n", num);       /* Output 6*/          }

The two num variables in the above example are local variables and are visible only in the function itself. As we said earlier, the two functions with the same name will not interfere with each other, that is the truth. So the above two outputs, in the main function is still 5, the output in the Add () function is 6.

2. Global scope

For variables with global scope, we can access them anywhere in the program. When a variable is declared outside of all functions, that is, at the beginning of the program, the variable is a global variable.

void add (int);          int num;          Main ()          {              int n=5;              Add (n);              printf ("%d\n", num);      /* Output 6*/          }          void Add (num)/          * Formal parameter not specified type */          {              num++;              printf ("%d\n", num);      /* Output 6*/          }

The above main () and add () do not declare num, but at the end of the output it is required to output num, because at the beginning of the program it is declared that NUM is a global variable, that is, the variable can be used in all functions. At this point the value of the variable is changed in a function, and the values in the other functions are affected. The above example output is 6 because the value of NUM is changed in the Add () function, since NUM is a global variable, as if their two functions share a variable, so num in the main () function changes as well.

  

3. File scope

In many C language books, there is no description of the scope of the file, or just a slight mention, in fact, the file scope in the larger program is very useful (in a multi-file system). A file scope is an external identifier that is visible only in summary functions within the same translation unit that declares it. The so-called conversion Unit refers to the source code files that define these variables and functions (including any source code files that are contained by the #i nclude directive). The static storage type modifier Specifies that the variable has a file scope.

       static int num;          static void Add (int);          Main ()          {              scanf ("%d", &num);              Add (num)              printf ("%d\n", num);          }          void Add (num)          {              num++;          }

The above program in the variables num and the function add () in the declaration is the static storage type modifier, which makes them have file scope, only the love definition of their files within the visible.


Since most of the programs we mention have only one compilation file, this is not really meaningful. However, there are many documents in the actual project, they are not written by one person, they are done by a lot of people, these files are compiled separately, it is inevitable that some people use the same global variable name, then in order to later in the program of the respective variables and functions do not interfere with each other, you can use the static modifier, so is not visible in other code files that are connected to the same program.

Second, the variable storage type

As we said earlier, declaring a variable is in a similar form:

int Num;float Total;

None of them have storage type modifiers, and we can also tell the compiler what type of variables to process by storing type modifiers when declaring. There are four types of storage: Automatic (auto), Static, external (extern), register (regiser).

1. Automatic storage type

The automatic storage type modifier Specifies that a local variable is automatic, which means that each time the statement block that defines the variable is executed, a new copy is generated in memory for that variable and initialized. In fact, if not specifically indicated, the local variable storage type is automatically the default, therefore, the addition of auto can be.

Main ()   {         Auto int num=5;         printf ("%d\n", num);   }

In this example, the execution of the code is the same regardless of whether the declaration of the variable num contains the keyword auto. The form parameter storage type of a function is also automatic by default.

2. Static storage variables

The static keyword has been used before, but for local variables, the meaning of the statically stored type is different, which is relative to the automatic storage type. The scope of a static local variable is still nearly limited to the statement block that declares it, but the variable will always hold its value during the execution of the statement block. Also, the initialization value only works if the statement block is executed for the first time. During the subsequent run, the variable retains the value of the last execution of the statement block.

See the following two corresponding programs:

       /*1.c*//*2.c*/int Add ();            int add (); Main () main () {{int resul                            T                int result;                Result=add () Result=add ();                  printf ("%d", result);                printf ("%d", result);                          Result=add ();                Result=add ();                  printf ("%d", result);                printf ("%d", result);                          Result=add ();                Result=add ();                   printf ("%d", result);            printf ("%d", result);                                      }} int Add () int add () {                            {int num=50;                static int num=50;                     num++;            num++;                            return num;            return num; }                                      }

Above two source files, only the variable declaration in the function add () is different, one is the automatic storage type, and the other is the static storage type.

for 1. c file, the output is 51 51 51; This is good to understand, each time the initial value is 50, and then add 1 up.

for 2. c file, the output is 51 52 53; This is because the variable is static, only 50 is initialized for the first time, and the last result value is used later. When the first call to add () is initialized to 50, then add 1, the output is 51, when the second call is not initialized, then the value of NUM is the last 51, then add 1, Output 52, when the third call, Num is 52, plus 1 is 53.

Comparisons will find their differences. Static variables are often used in the next SectionTo recursive function.

When the initial value of a static variable is not specified for the first time, the default is 0.

Let's take an example to understand the static variables we're talking about.

The code for the value of 1+2+......+100 is as follows:

void Add ();           int result;           Main ()           {               int i;               result=0;               for (i=0;i<100;i++) add ();               printf ("%d\n", result);           }           void Add ()           {               static int num=0;               num++;               Result+=num;           }

  

The Add () function is called 100 times, and Num's values change from 11 to 100, so that they can be calculated. If you write an int num=0, that's the value of 1+1+......+1 100 1.

In fact, similar problems can be solved by recursive functions, and what is recursive is described in the next section.

3. External Storage type

An external storage type declares an external variable that the program will use, but not yet defined. Typically, an external storage type is used to declare a variable that is defined in another translation unit. For example, this example includes two files.

/*1.c*/              void A ();              Main ()              {                  extern int num;                  A ();                  printf ("%d\n", num);              }               /*2.c*/              int num;              void A ()              {                  num=5;              }

The two programs are compiled separately and then connected to an execution file. How to do this, you can see some manuals, here I briefly said. After compiling all two files, make a. prj file with the following:

1.c
2.c


Only these two lines, this can be written in the editing state, save, named 1.prj.
Then select the Project option, select Project name, fill in the 1.PRJ filename, and press F9 to generate the 1.exe file.

  

The variable num in the main () function is defined in another file. Therefore, when the compiler compiles 1.c, the address of the variable cannot be determined. At this point, the external storage type declaration tells the compiler to treat all references to Num as an indeterminate reference, and then to handle the reference to the variable num when all the cheap good target code is connected to an executable module.

  

The declaration of an external variable can be either inside or outside the function that references it. If the variable is declared outside the function, then all functions within the same conversion unit can use the external variable. Conversely, if inside a function, then only this function can use the variable.

The problem with file scope is mentioned earlier, if the global variable is declared with the static modifier, then the variable is only visible within the current file, and extern can refer to variables in other files. So in a large program, each programmer just completes a small piece, in order to let their own variables not used by other programmers, maintain a certain degree of independence, often in front of the global variables and static. We can illustrate this by:

Or the above two files, now add a file 3.c, the content is:

static int num;   void A ()   {        num=6;   }

Add 3.c to the 1.prj file so that we generate a 1.exe file that executes when the output is 5 instead of 6. Because the NUM variable of the 3.c file increases the file scope, it cannot be used in other files.

4. Register Storage Type

A variable declared as a register store type, except that the program cannot get its address, and the rest is the same as an automatic variable. As for what is the variable address, it is described in detail later when the pointer is said.

Main ()  {      egister int num;      num=100;      printf ("%d", num);  }

The purpose of using a register storage type is to have the programmer specify that a local variable is stored in a hardware register in the computer rather than in memory to increase the speed of the program. However, this only reflects the programmer's subjective will, and the compiler can ignore the Register store type modifier.

The address of the register variable cannot be obtained because the hardware registers of most computers do not occupy memory addresses. Furthermore, even if the compiler ignores the register type modifier and places the variable in the memory of the settable address, the restriction that we cannot take the address still exists.

To make efficient use of register storage types, you must understand the internal structure of the processor as assembler programmers do, know the number and kind of registers that can be used to hold variables, and how they work. However, different computers may not be the same in these details, so for a portable program, the Register storage type is not very useful. Especially now a lot of compilers can provide good optimization effect, far more effective than the programmer to choose. However, the register storage type can also provide an important reference for the optimizer.

The scope of C also has a static block. Like what:

/* static block scope */{...; ...;} /* Function Scope */main () {...;}

Stack

Release management is automatically assigned by the compiler. Local variables and the return address of each function call, and the caller's environment information (for example, some machine registers) are stored in the stack. The newly called function allocates storage space for its automatic and temporary variables on the stack. By using the stack in this way, the C function can be called recursively.

Heap

Release management needs to be assigned by the programmer, and if the programmer does not release it, it may be recycled by the OS at the end. Dynamic storage allocations are typically performed in the heap.


Non-initialized data segment

This segment is often referred to as the B S-S segment, which is derived from an operator of the early assembler, meaning "block started by symbol (blocks starting with symbols)", where uninitialized global variables and static variables are stored. The kernel initializes this segment to 0 before the program begins execution. Description outside the function: Long sum[1000]; Causes this variable to be stored in a non-initialized data segment.

  

Initialized data

This segment is often referred to as a data segment, which contains variables that need to be assigned an initial value in the program. The initialized global variables and static variables are stored here. For example, a description outside any function in the C program: int maxcount = 99; Causes this variable to be stored in the initialization data segment with an initial value.

  

Body Segment

The part of the machine instruction that the CPU executes. Normally, the body segment is shareable, so even a program that is executed by a regular environment pointer environment string (such as a text editor, C compiler, S H e L, etc.) can only have one copy in memory, and the body segment is often read-only to prevent the program from modifying its own instructions due to an accident.


For Linux on the x86 processor, the body segment starts at the 0x08048000 unit and the bottom starts below 0xc0000000 (the stack grows from the high address to the low address direction). The unused virtual space between the top of the heap and the bottom of the stack is large.


The shell's size command can see the body of a program (text), data, non-initialized data segment (BSS), and file length.

[[Email protected]:01:49] $size mydesign   text    data     BSS     Dec     hex filename79210    1380     404   80994   13c62 mydesign

A detailed explanation of the C + + heap, stack, and static data area is explained here.

Finally, hope that the reprint of friends can respect the author's labor results, plus reprint address: http://www.cnblogs.com/hanyonglu/archive/2011/04/12/2014212.html Thank you.

Complete. ^_^

A detailed description of the C + + heap, stack and static data area

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.