C language memory layout understanding

Keywords: C C# Windows Back-end

Edit: is to create and modify the source code of C program - the program we write is called source code.
Compilation: is to convert the source code into machine language. The output of the compiler becomes the object code, and the file in which they are stored is called the object file. The extension is. o or. obj.
(this partial compilation refers to the compiler compiling assembly language or compiler compiling high-level language)
Link: the linker combines various modules of the source code generated by the compiler, and then adds necessary code modules from the program library provided by C language to form an executable file. The extension is. exe under windows and no extension under Unix.
Execute: run the program.

 

Text segment (text)
         Usually, code segments and read-only data segments are combined into text segments, which contain the actual code (machine instructions) and constants to be executed. It is usually shared. Multiple instances share text segments, which cannot be modified.

Code snippet
         The code segment consists of machine code executed in the program. In C language, program statements are compiled to form machine code. During the execution of the program, the program counter of the CPU points to each piece of machine code in the code segment and is run by the processor in turn.

Read only data segment (RO data, i.e. constant area)
         The read-only data segment is some data that will not be changed by the program. The way of using these data is similar to the look-up table operation. Because these variables do not need to be changed, they only need to be placed in the read-only memory.

        Usually, string constants are placed here and released by the system after the program is completed.

         Note: whether this area exists or not has always been a controversial issue, but we agree that it does exist here, because there is an area different from other data segments in our program, but often we call the read-only data segment (RO data) and the following initialized read-write data segment (RW data) together as data segment data, But in fact, this is inappropriate because the read-write permissions of the two regions are different during execution. As the name suggests, the read-only data segment (RO data) is read-only, and the initialization read-write data segment is readable and writable.

  

Initialized read / write data segment (RW data)
        Initialized data are variables declared in the program and with initial values. These variables need to occupy memory space. When the program is executed, they need to be located in the readable and writable memory area and have initial values for reading and writing when the program is running.

Uninitialized data segment (BSS)   Block Started by Symbol)
        Uninitialized data are variables declared in the program but not initialized or initialized to 0. These variables do not need to occupy memory space before the program runs. The variables in the BSS section have only name and size but no value. They will be initialized to 0 after running.

Dynamic & static

         When a program is loaded into memory, there are two properties of this memory: statically allocated memory and dynamically allocated memory.  
Statically allocated memory: it is the memory determined when the program is compiled and linked.  
Dynamic memory allocation: it refers to the memory allocated / reclaimed during program loading, calling in and execution.

         Code segment, read-only data segment, read-write data segment and uninitialized data segment belong to static area, and heap and stack belong to dynamic area. Code segments, read-only data segments and initialization read-write data segments are generated after the program is linked and exist in the executable file. However, uninitialized data segments (BSS) will be opened up during program initialization, and the heap and stack will be allocated and released as dynamic areas during program operation.

 

 

Reprinted from: https://blog.csdn.net/gatieme/article/details/43567433

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#define SHW_VAR_ADR(ID, I)                    \
printf("the %20s\t is at adr:%p\n", ID, &I); //Print variable address macro

#define SHW_POT_ADR(ID, I)                    \
printf("the %20s\t is at adr:%p\n", ID, I);  //The print pointer points to the address macro

extern int func(void);
extern void afunc(void);

/*extern etext, edata, end;*/

/**
(1)Global variables and static variables are stored together,
The initialized global variables and static variables are in one area (RW data),
Uninitialized global variables and uninitialized static variables are in another adjacent area (BSS).
System release after program
 As described in (1). 1 (1). 2 (1). 3 below
**/
// (1) . 1 -- as long as it is a static variable, even if it is local, it is not stored in the stack, but in the static area, and stored in the BSS segment and DATA segment respectively according to whether it is initialized or not
static int /*bss_*/unini_glo_sta_var;                           //  Static uninitialized global variables are still stored in the BSS area, although the system will initialize to 0 by default
static int /*data_*/ini_glo_sta_var = 10;                       //  Statically initialize global variables and store them in RW DATA area

// (1) . 2 -- as long as it is a global variable, it is stored in the static area and stored in the BSS segment and DATA segment respectively according to whether it is initialized or not
int /*bss_*/unini_glo_var;                                      //  Uninitialized global data is stored in the BSS data area
int /*data_*/ini_glo_var = 42;                                  //  The initialization global data is stored in the RW DATA area

// (1) . 3 -- global constant, which itself is a global variable, that is, stored in the static area, the same as (1). 2
==========The original text is const int unini_glo_cnt_var;however vs This definition is not allowed on, const Variables must be initialized, as shown below(2).2 Similarly
int unini_glo_cnt_var;                                        //  Uninitialized global constant [unsafe], automatically initialized to 0, but still stored in BSS area  
const int ini_glo_cnt_var = 10;                                     //  Initialize the global constant and store it in the constant area
// The problem we need to pay attention to for constants is that they are not stored in the constant area (RO data) as we expect,
// The constant area is only used to store initialized global constants and string variables themselves (not pointers)
// Local constants are still stored on the stack as local quantities
// Because the constant area and code segment are together (in some segment classification results, there is no constant area, and the constant area and code segment are combined into code area)
// In itself, constants only limit their read-write permissions, which can be formulated and restricted by the compiler at the compilation stage,
// In this way, under the strict compiler review results, there will be no reading and writing operations on constants in the run-time code, so it is not necessary to store other local constants in the constant area
// Otherwise, the code segment will be bloated...

static int unini_glo_sta_cnt_var;
static int ini_glo_sta_cnt_var = 10;

int main(void)
{
    char *p_alloca = NULL, *b_malloc = NULL, *nb_malloc = NULL;

    // (1) . 4 local static variables are still static variables, the same as (1). 1
    static int unini_sta_var;               //  Local uninitialized static variables are stored in the BSS segment
    static int ini_sta_var = 10;            //  Statically initialize local variables and store them in the DATA section

    // Local non static variables are stored on the stack
    // (2) . 1 -- local variables (whether initialized or not) are stored in the stack
    int unini_var;                          //  Local uninitialized variable,
    int ini_var = 10;                       //  Local initialization variable

    //  (2) . 2 -- local constants (whether initialized or not) are stored in the stack, the same as (2). 1
    int unini_cnt_var;            // Uninitialized local constants are unsafe and stored on the stack
    const int ini_cnt_var = 10;         // Local constants, stored on the stack

    //  (2) . 3 -- pointer constant and constant pointer, whose essence is local variable or local constant, are stored in the stack, the same as (2). 1 (2). 2
    const int *p_cnt_var = &ini_cnt_var;   //  pointer to const 
    int * const cnt_p_var = &ini_var;       //  constant pointer 
    const int * const cnt_p_cnt_var = &unini_cnt_var;    // Constant pointer to constant

    // (3) The string constant is stored in the constant area. In vs, the string constant must be explicitly defined as const char *. If only char * = "ABCDE", an equal sign will be reported twice with different types
    const char* str_cnt = "ABCDE";      //  String face variable, stored in constant area, i.e. (RO data)
                                            //  This code is equivalent to const char* str1 = "ABCDE"
    char str_array[] = "ABCDE";             //  Character array, equivalent to initialized local variables, is stored in the stack


/*    printf("Adr etext:%8x\t Adr edata %8x\t Adr end %8x\t\n", &etext, &edata, &end);*/

    // TEXT snippet -- code snippet
    printf("------------------------------------------------------\n");
    printf(".Text Location:\n");
    SHW_VAR_ADR("main", main);              //View code snippet main function location
    SHW_VAR_ADR("afunc", afunc);           //View code snippet afunc function location
    printf("------------------------------------------------------\n\n");

    // BSS segment -- uninitialized global variable area
    printf("------------------------------------------------------\n");
    printf(".Bss Location:\n");
    SHW_VAR_ADR("unini_glo_sta_var", unini_glo_sta_var);                //  Global uninitialized static variable, in BSS segment
    SHW_VAR_ADR("unini_sta_var", unini_sta_var);                        //  Static variable not initialized, in BSS segment
    SHW_VAR_ADR("unini_glo_cnt_var", unini_glo_cnt_var);                //  Global uninitialized constant, in BSS section
    SHW_VAR_ADR("unini_glo_var", unini_glo_var);                        //  The global uninitialized variable is in the BSS section
    SHW_VAR_ADR("unini_glo_sta_cnt_var", unini_glo_sta_cnt_var);        //  Global uninitialized static constant, in BSS section
    printf("------------------------------------------------------\n\n");


    // RW DATA segment -- read / write initialized data segment
    printf("------------------------------------------------------\n");
    printf(".Data Location:\n");
    SHW_VAR_ADR("ini_glo_sta_var", ini_glo_sta_var);                    //  Global initialization static variables are stored in the RW data area
    SHW_VAR_ADR("ini_glo_var", ini_glo_var);                            //  Global initialization variables are stored in RW data

    SHW_VAR_ADR("ini_sta_var", ini_sta_var);                            //  Local initialization static variables are stored in the RW data area

    SHW_VAR_ADR("ini_glo_sta_cnt_var", ini_glo_sta_cnt_var);            //  The global static initialized constant is stored in the RW data area
    printf("------------------------------------------------------\n\n");

    // RO data -- read only data segment
    printf("------------------------------------------------------\n\n");
    printf("RW data");
    SHW_VAR_ADR("ini_glo_cnt_var", ini_glo_cnt_var);     // Initializes the global constant, which is located in the text area, that is, the constant area, just like the string face variable
    SHW_POT_ADR("str_cnt", str_cnt);                  //  String face variables are saved in the constant area, that is, the text area
    SHW_VAR_ADR("str_cnt", str_cnt);             //  The pointer str1 itself is on the stack

    printf("------------------------------------------------------\n\n");

    // STACK -- STACK
    printf("------------------------------------------------------\n");
    printf("Stack Locations:\n");
    afunc();                                    //   Call 5 this afunc function recursively

    p_alloca = (char *)alloca(32);              //   Allocate space from the stack and release it immediately after use
    if (p_alloca != NULL)
    {
        SHW_VAR_ADR("start", p_alloca);
        SHW_VAR_ADR("end", p_alloca + 31);
    }


    // Local variables (whether initialized or not) are stored on the stack
    SHW_VAR_ADR("unini_var", unini_var);
    SHW_VAR_ADR("ini_var", ini_var);

    //  Local constants (whether initialized or not) are stored on the stack
    SHW_VAR_ADR("unini_cnt_var", unini_cnt_var);        // Uninitialized local constants are unsafe and stored on the stack
    SHW_VAR_ADR("ini_cnt_var", ini_cnt_var);            // Local constants, stored on the stack

    //  Pointer constant and constant pointer, whose essence is local variable or constant, are stored in the stack
    SHW_VAR_ADR("p_cnt_var", p_cnt_var);            //  The pointer to the constant itself is actually a (initialized) local variable [same as inI]_ Var], stored on the stack
    SHW_VAR_ADR("cnt_p_var", cnt_p_var);            //  The pointer constant itself is actually an initialized local constant [the same as ini_cnt_var], stored on the stack
    SHW_VAR_ADR("cnt_p_cnt_var", cnt_p_cnt_var);    //  The pointer constant pointing to the constant is stored on the stack as an initialized local constant

    SHW_POT_ADR("str_array", str_array);             //  String array, equivalent to initialized local variables, is saved in the stack
    SHW_VAR_ADR("str_array", str_array);             //  The pointer str2 itself is on the stack, and its address itself is the address of the string array

    printf("------------------------------------------------------\n\n");


    printf("------------------------------------------------------\n");
    printf("Heap Locations:\n");
    b_malloc = (char *)malloc(32 * sizeof(char));   //Allocate space from heap
    nb_malloc = (char *)malloc(16 * sizeof(char));  //Allocate space from heap
    printf("the Heap start: %p\n", b_malloc);   //Heap start position
    printf("the Heap end:%p\n", (nb_malloc + 16 * sizeof(char)));//Heap end position

    // The area pointed to by the pointer is in the heap, but the pointer itself is in the stack
    printf("\nb and nb in Stack\n");
    SHW_VAR_ADR("b_malloc", b_malloc);       //Displays the position of data b in the stack
    SHW_VAR_ADR("b_malloc", nb_malloc);      //Displays the position of data nb in the stack
    free(b_malloc);               //Free up the requested space to avoid memory leaks
    b_malloc = NULL;
    free(nb_malloc);              //Free up the requested space to avoid memory leaks
    nb_malloc = NULL;
    printf("------------------------------------------------------\n\n");

    func();

    return EXIT_SUCCESS;
}

void afunc(void)
{
    static int long level = 0;          // Static data is stored in data segments
    int      stack_var;                 // Local variables, stored in the stack area
    if (++level == 5)                   // This function is called recursively 5 times
    {
        return;
    }
    printf("stack_var is at:%p\n", &stack_var);
    //      SHW_VAR_ADR("stack_var in stack section",stack_var);
    //      SHW_VAR_ADR("Level in data section",level);
    afunc();
}
//main.cpp 
 
int a = 0; Global initialization area XXX,Variables initialized to 0 are stored in the global uninitialized area
 
char *p1; Global uninitialized area 
 
main() 
 
{ 
 
int b;// Stack 
 
char s[] = "abc"; //"abc" is in the constant area and s is on the stack. 
 
char *p2; //Stack 
 
char *p3 = "123456"; //123456\0"; In the constant area, p3 is on the stack. 
 
static int c =0; //Global (static) initialization area 
 
p1 = (char *)malloc(10); 
 
p2 = (char *)malloc(20); 
 
//The allocated areas of 10 and 20 bytes are in the heap area. 
 
strcpy(p1, "123456"); //123456 \ 0 is placed in the constant area, and the compiler may optimize it in the same place as the "123456" pointed to by p3. 
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

static int a;
static int b = 0;
static int c = 8;

int d;
int e = 0;
int f = 3;

int main()
{
    static int g;
    static int h = 0;
    static int i = 9;

    int j;
    int k = 0;
    int m = 28;



    printf("&a = %p &b = %p &c = %p\n", &a, &b, &c);
    printf("&d = %p &e = %p &f = %p\n", &d, &e, &f);
    printf("&g = %p &h = %p &i = %p\n", &g, &h, &i);
    printf("&j = %p &k = %p &m = %p\n", &j, &k, &m);

    return 0;
}

Output results:
&a = 00D7431C &b = 00D74320 &c = 00D74008
&d = 00D74314 &e = 00D74318 &f = 00D74004
&g = 00D74324 &h = 00D74328 &i = 00D7400C
&j = 0038FAA0 &k = 0038FA94 &m = 0038FA88

//The contents of the stack area are written with the high address first and then the low address

Posted by pingu on Sat, 04 Sep 2021 22:29:49 -0700