C + + core programming: memory partition model

During the execution of C + + program, the general direction of memory is divided into four areas:

  • Code area: it stores the binary code of the function body and is managed by the operating system.
  • Global area: stores global variables, static variables and constants.
  • Stack area: automatically allocated and released by the compiler to store function parameter values, local variables, etc.
  • Heap area: it is allocated and released by the programmer. If the programmer does not release it, it will be recycled by the operating system at the end of the program.

Meaning of four memory areas:

The data stored in different areas gives us different life cycles and gives us greater flexibility in programming.

Before program running: (global area)

After the program is compiled, an exe executable program is generated. Before the program is executed, it is divided into two areas:

Code area:

  • Store machine instructions executed by CPU: binary 01010.
  • characteristic:
    • The code area is shared. The purpose of sharing is to have only one code in memory for frequently executed programs.
    • The code area is read-only because it prevents the program from accidentally modifying its instructions.

Global area:

  • Global and static variables are stored here.
  • The global area also contains a constant area, where string constants and other constants are stored.
    • characteristic:
      • The data in this area is released by the operating system after the program ends.

Other constants: const modified global variables. (global constant)

Data stored in the global area: global variables, static variables and constants.

Local variable: a variable declared in a function body. Included in the main function.

Global variable: a variable declared outside a function.

const modification or not:

  • Constant: its value cannot be modified.
  • Variable: its value can be modified.

Whether static is modified or not:

  • Static:
  • Non static:
#include<iostream>
using namespace std;


// Create global variable
int g_a = 10;
int g_b = 20;

// const decorated global constant.
const int c_g_a = 10;
const int c_g_b = 20;


int main()
{
	// Global area: stores global variables, static variables and constants.

	// Create a normal local variable
	int a = 10;
	int b = 20;

	cout << "local variable a Address bits:" << (int)&a << endl;
	cout << "local variable b Address bits:" << (int)&b << endl;
	cout << endl;

	cout << "global variable g_a Address bits:" << (int)&g_a << endl;
	cout << "global variable g_b Address bits:" << (int)&g_b << endl;

	// Static variable: add static before ordinary variable
	static int s_a = 10;
	static int s_b = 20;
	cout << "Static variable s_a Address bits:" << (int)&s_a << endl;
	cout << "Static variable s_b Address bits:" << (int)&s_b << endl;
	cout << endl;

	// Constant: it is divided into string constant and const modified variable.
	// 
	// String constant: a string enclosed in double quotation marks can be called a string constant. "Hello world.". 
	cout << "The address of the string constant is:" << (int)&"hello world" << endl;

	// Const modified variable: it can also be divided into: const modified global constant and const modified local variable (local constant).
	cout << "Global constant c_g_a Your address is:" << (int)&c_g_a << endl;
	cout << "Global constant c_g_b Your address is:" << (int)&c_g_b << endl;

	cout << endl;   // The local constant is not in the global area.
	const int c_l_a = 10;
	const int c_l_b = 20;
	cout << "Local constant c_l_a Your address is:" << (int)&c_l_a << endl;
	cout << "Local constant c_l_b Your address is:" << (int)&c_l_b << endl;

	system("pause");
	return 0;
}

Output:

local variable a Address bit: 9435924
 local variable b Address bit: 9435912

global variable g_a Address bit: 11583540
 global variable g_b Address bit: 11583544
 Static variable s_a Address bit: 11583548
 Static variable s_b Address bit: 11583552

The address of the string constant is 11574108
 Global constant c_g_a The address of is 11574920
 Global constant c_g_b The address of is 11574924

Local constant c_l_a The address of is 9435900
 Local constant c_l_b Your address is 9435888

Observations:

  • The addresses of global variables, static variables, global constants and string constants are very close, and they are placed in the same area (global area).  
  • The addresses of local variables and local constants are very close, and they are placed in the same area (stack).

After the program runs: (stack area)

It is automatically allocated and released by the compiler to store the parameter values and local variables of the function.

Note: do not return the address of the local variable. The stack area is open

The generated data is automatically released by the compiler.

#include<iostream>
using namespace std;

int* func()
{
	int a = 10;  // Local variables are stored in the stack area, and the data in the stack area is automatically released after the function is executed.
	return &a;   // Returns the address of a local variable.
}

int main()
{
	int* p = func();
	
	cout << *p << endl;   // 10
	cout << *p << endl;   // 2055768456


	system("pause");
	return 0;
}

Output:

The correct number can be printed for the first time. Because the compiler is afraid of misoperation, it will make a reservation. But the second time this number is no longer retained.

Therefore, the address of the local variable must not be returned. Because it was released after running once. Then operate the memory with a pointer, and the memory no longer belongs to the variable.

New questions:

Suppose that when a function has formal parameters, the result is different:

#include<iostream>
using namespace std;

//int* func() 
int* func(int b) 
{
	b = 100;
	cout << "Formal parameter b The memory address of is:" << (int)&b << endl;    // 5242140
	int a = 10;  // Local variables are stored in the stack area, and the data in the stack area is automatically released after the function is executed.
	return &a;   // Returns the address of a local variable.
}

int main()
{
	int num = 1;
	int* p = func(num);
	cout << "Argument num The memory address of is:" << (int)&num << endl;  // 5242364
	
	cout << *p << endl;   // 5312572
	cout << *p << endl;   // 5312572
	cout << *p << endl;   // 5312572



	system("pause");
	return 0;
}

Output:

At this time, I mask the code step by step and try to find the reason: when

When 17 lines and 18 lines in main are masked for printing.

#include<iostream>
using namespace std;

int* func() 
//int* func(int b) / / the formal parameter data will also be placed in the stack area.
{
	//b = 100;
	//Cout < < the memory address of parameter b is: < < (int) & b < < endl// five million two hundred and forty-two thousand one hundred and forty
	int a = 10;  // Local variables are stored in the stack area, and the data in the stack area is automatically released after the function is executed.
	return &a;   // Returns the address of a local variable.
}

int main()
{
	int num = 1;
	int* p = func();
	//Cout < < "the memory address of argument num is:" < (int) & num < < endl// five million two hundred and forty-two thousand three hundred and sixty-four
	//Cout < < "the memory address of argument num is:" < (int) & num < < endl// five million two hundred and forty-two thousand three hundred and sixty-four
	
	cout << *p << endl;   // 5312572
	cout << *p << endl;   // 5312572
	cout << *p << endl;   // 5312572



	system("pause");
	return 0;
}

 

When I release print:

#include<iostream>
using namespace std;

int* func() 
//int* func(int b) / / the formal parameter data will also be placed in the stack area.
{
	//b = 100;
	//Cout < < the memory address of parameter b is: < < (int) & b < < endl// five million two hundred and forty-two thousand one hundred and forty
	int a = 10;  // Local variables are stored in the stack area, and the data in the stack area is automatically released after the function is executed.
	return &a;   // Returns the address of a local variable.
}

int main()
{
	int num = 1;
	int* p = func();
	cout << "Argument num The memory address of is:" << (int)&num << endl;  // 5242364
	//Cout < < "the memory address of argument num is:" < (int) & num < < endl// five million two hundred and forty-two thousand three hundred and sixty-four
	
	cout << *p << endl;   // 5312572
	cout << *p << endl;   // 5312572
	cout << *p << endl;   // 5312572



	system("pause");
	return 0;
}

Output:

Further experiments:

#include<iostream>
using namespace std;

//int* func() 
int* func(int b)   // The formal parameter data will also be placed in the stack area.
{
	b = 100;
	cout << "Formal parameter b The memory address of is:" << (int)&b << endl;    // 5242140
	int a = 10;  // Local variables are stored in the stack area, and the data in the stack area is automatically released after the function is executed.
	return &a;   // Returns the address of a local variable.
}

int main()
{
	int num = 1;
	int* p = func(num);
	//Cout < < "the memory address of argument num is:" < (int) & num < < endl// five million two hundred and forty-two thousand three hundred and sixty-four
	//Cout < < "the memory address of argument num is:" < (int) & num < < endl// five million two hundred and forty-two thousand three hundred and sixty-four
	
	cout << *p << endl;   // 5312572
	cout << *p << endl;   // 5312572
	cout << *p << endl;   // 5312572



	system("pause");
	return 0;
}

Output:

In other words, as long as main does not print in advance and does not call cout, it will be fine. Once cout outputs other data once before printing the pointer, the pointer will remain unchanged.

I don't know the reason for this problem. If you have any friends who know, please leave a message in the comment area to let me know.

Heap: new and delete

It is allocated and released by the programmer. If the programmer does not release it, it will be recycled by the operating system at the end of the program.

In C + +, the new keyword is mainly used to open up memory in the heap.

#include<iostream>
using namespace std;

int* func()
{
	//int a = 10;
	//return &a;
	// 
	// Use the new keyword to open up the data to the heap.
	// The pointer is also a local variable in nature and is also placed in the stack area, but the actual data saved by the pointer is in the heap area.
	int* p = new int(10);
	return p;
}


int main()
{
	int* p = func();
	cout << *p << endl;   // 10
	cout << *p << endl;   // 10
	cout << *p << endl;   // 10


	system("pause");
	return 0;
}

  

Pointer is a type. 4 bytes, stored in the stack. The data content of the stack is the memory address pointed to.

Use the new keyword to open up space in the memory heap to store data.

A * P = new a (value); An address is returned.

Create A new variable that points to the address of type A data in the heap.

The programmer can free up memory space: delete

#include<iostream>
using namespace std;


int* func()
{
	// Create an integer data in the heap.
	// new returns a pointer to the data type.
	int* p = new int(10);
	return p;
}

void test01()
{
	int* p = func();
	cout << *p << endl;  // 10
	cout << *p << endl;  // 10
	// As long as the programmer does not actively release the data in the heap, it will always exist.
	// The data in the heap area is managed by the programmer and released by the programmer.
	// If you want to release the data in the heap, use the keyword delete
	delete p;
	//cout << *p << endl;  //  Exception thrown: read access violation. The memory has been released. It is illegal to access it again, and an error will be reported.

}

void test02()
{
	// Open up an array in the heap:
	int* arr = new int[10];   // Returns the first address of a contiguous array.
	for (int i = 0; i < 10; i++)
	{
		arr[i] = i + 100;
	}
	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << endl;
	}
	// Free heap array:
	// When releasing an array, you need to add [].
	delete[] arr;

}

int main()
{
	test01();
	test02();
	system("pause");
	return 0;
}

Explanation of one line of code:

See a line of code: int a = 10;

int represents integer, and 4 bytes are opened in the memory stack area to save data. The data value is 10. This area is represented by a.  

 

Keywords: C++ memory management

Added by studgate on Sun, 09 Jan 2022 09:15:54 +0200