Memory allocation of heap, stack, global, local and other variables in C programs under Ubuntu and stm32

1, Memory distribution

1. Address details

In an STM32 program code, stack area, heap area, global area (static area), constant area and code area are successively distributed from high memory address to low memory address, in which. bss segment is distributed in high address and. data segment is distributed in low address.
The total distribution is as follows:

Memory high addressStack area
Heap area
. bss segment
. data segment
Constant area
Memory low addressCode area

1) Stack area

  • Temporarily created local variables are stored in the stack area.

  • When a function is called, its entry parameters are stored in the stack area.

  • When the function returns, its return value is stored in the stack area.

  • The local variables defined by const are stored in the stack area.

2) Heap area

  • Heap area is used to store memory segments dynamically distributed during program operation, which can be increased or decreased.

  • malloc and other functions can be used to dynamically distribute memory.

  • The memory distributed by malloc function must be released with free, otherwise it will cause memory leakage.

3) Global area (static area)
The global area has bss segment and data segment, readable and writable.

4). bss segment

  • Uninitialized global variables are stored in bss segment.

  • Global variables initialized to 0 and static variables initialized to 0 are stored in bss segment.

  • . bss segment does not occupy executable file space, and its contents include operating system initialization.

5). data segment

  • The initialized global variables are stored in the data segment.

  • Static variables are stored in data segment.

  • . The data section occupies the executable file space, and its contents include program initialization.

  • The global variables defined by const are stored in rodata section.

6) Constant area

  • The string is stored in the constant area.

  • The contents of the constant area cannot be modified.

7) Code area

  • The program execution code is stored in the code area.

  • String constants may also be stored in the code area.

2. Data storage location

  • RAM (random access memory)

The stored contents can be accessed randomly by instructions. The data stored in RAM will be lost during power failure, so it can only be stored during startup and operation. RAM can be divided into two types, one is Dynamic
RAM(DRAM dynamic random access memory), the other is Static
RAM(SRAM, static random access memory). Stack, heap and global area (. bss segment and. data segment) are stored in RAM.

  • ROM (read only memory)

You can only read data from it, not write data arbitrarily. Compared with RAM, ROM has the disadvantage of slow reading and writing speed. However, because it has the advantage that the data can remain unchanged after power failure, it is often used to store one-time written programs and data. For example, the chip of the main BIOS program is ROM memory. The contents of code area and constant area are not allowed to be modified, so they are stored in ROM.

2, Programming verification

1) Code addition
First, create files in Ubuntu and keil, and add the following code:

#include <stdio.h>
#include <stdlib.h>
//Define global variables
int init_global_a = 1;
int uninit_global_a;
static int inits_global_b = 2;
static int uninits_global_b;
void output(int a)
{
	printf("hello");
	printf("%d",a);
	printf("\n");
}

int main( )
{   
	//Define local variables
	int a=2;
	static int inits_local_c=2, uninits_local_c;
    int init_local_d = 1;
    output(a);
    char *p;
    char str[10] = "lyy";
    //Define constant string
    char *var1 = "1234567890";
    char *var2 = "qwertyuiop";
    //Dynamic allocation
    int *p1=malloc(4);
    int *p2=malloc(4);
    //release
    free(p1);
    free(p2);
    printf("Stack area-Variable address\n");
    printf("                a : %p\n", &a);
    printf("                init_local_d: %p\n", &init_local_d);
    printf("                p: %p\n", &p);
    printf("              str: %p\n", str);
    printf("\n Heap area-Dynamic application address\n");
    printf("                   %p\n", p1);
    printf("                   %p\n", p2);
    printf("\n Global area-Global and static variables\n");
    printf("\n.bss paragraph\n");
    printf("Global external no initial value uninit_global_a: %p\n", &uninit_global_a);
    printf("Static external no initial value uninits_global_b: %p\n", &uninits_global_b);
    printf("Static internal no initial value uninits_local_c: %p\n", &uninits_local_c);
    printf("\n.data paragraph\n");
    printf("Global external initial value init_global_a: %p\n", &init_global_a);
    printf("Static external initial value inits_global_b: %p\n", &inits_global_b);
    printf("Static internal initial value inits_local_c: %p\n", &inits_local_c);
    printf("\n Text constant area\n");
    printf("Literal constant address     : %p\n",var1);
    printf("Literal constant address     : %p\n",var2);
    printf("\n Code area\n");
    printf("Program area address       : %p\n",&main);
    printf("Function address         : %p\n",&output);
    return 0;
}

2) Compile run
① Under Ubuntu (work.c is the name of the file)

② On stm32 chip
First, since we need to send printf information to the host computer serial port assistant through the serial port, we need to add the serial port initialization function. After adding, it is as follows:

#include "stm32f10x.h" //STM32 header file
#include "sys.h"
#include "delay.h"

#include "usart.h"
#include <stdio.h>
#include <stdlib.h>
//Define global variables
int init_global_a = 1;
int uninit_global_a;
static int inits_global_b = 2;
static int uninits_global_b;
void output(int a)
{
	printf("hello");
	printf("%d",a);
	printf("\n");
}



int main (void){//main program
	u8 a=7,b=8;
	//Initialization program
	RCC_Configuration(); //Clock setting

	USART1_Init(115200); //Serial port initialization

	//Main cycle
	while(1){	
		int a=2;
	static int inits_local_c=2, uninits_local_c;
    int init_local_d = 1;
    output(a);
    char *p;
    char str[10] = "xz";
    //Define constant string
    char *var1 = "1234567890";
    char *var2 = "abcdefghij";
    //Dynamic allocation
    int *p1=malloc(4);
    int *p2=malloc(4);
    //release
    free(p1);
    free(p2);
    printf("Stack area-Variable address\n\r");
    printf("                a: %p\n\r", &a);
    printf("                init_local_d: %p\n\r", &init_local_d);
    printf("                p: %p\n\r", &p);
    printf("              str: %p\n\r", str);
    printf("\n Heap area-Dynamic application address\n\r");
    printf("                   %p\n\r", p1);
    printf("                   %p\n\r", p2);
    printf("\n Global area-Global and static variables\n\r");
    printf("\n.bss paragraph\n");
    printf("Global external no initial value uninit_global_a: %p\n\r", &uninit_global_a);
    printf("Static external no initial value uninits_global_b: %p\n\r", &uninits_global_b);
    printf("Static internal no initial value uninits_local_c: %p\n\r", &uninits_local_c);
    printf("\n.data paragraph\n\r");
    printf("Global external initial value init_global_a: %p\n\r", &init_global_a);
    printf("Static external initial value inits_global_b: %p\n\r", &inits_global_b);
    printf("Static internal initial value inits_local_c: %p\n\r", &inits_local_c);
    printf("\n Text constant area\n\r");
    printf("Literal constant address     : %p\n\r",var1);
    printf("Literal constant address     : %p\n\r",var2);
    printf("\n Code area\n\r");
    printf("Program area address       : %p\n\r",&main);
    printf("Function address         : %p\n\r",&output);


        delay_ms(1000); //delayed
		
	}
}

The results are as follows:

3, Result analysis

It can be seen from the above results that, firstly, under Ubuntu, the address values of stack area and heap area increase from top to bottom, while under stm32, the address value of stack area decreases from top to bottom, and the heap area increases from top to bottom.
According to Keil's compilation,
The memory distribution in Keil mainly includes Code, RO data, RW data and Zi data;
Their relationship with the size of RAM and ROM is:

RAM = RW-data + ZI-data

ROM = Code + RO-data + RW-data

4, Summary

Through this experiment, we can find that the memory allocation and size change of programs are different in different system environments. Only by understanding these knowledge more clearly can we make better use of them to solve problems.

5, Reference content

In C language, the memory addresses of local variables, global variables, static variables, heap and stack

Keywords: C Ubuntu stm32

Added by gaogier on Sun, 19 Dec 2021 19:10:53 +0200