Preamble: When you type a variable, where does the program put it? Why do you leak memory when you use Pointers rudely? In order to solve the above confusion, this article summarizes the relevant knowledge of C++ memory management.
What is a memory
Before we learn more about memory management, we need to know what memory is.
Memory is one of the most important parts in the computer. It is the bridge of communication with CPU. All programs in a computer are run in memory, so the performance of memory has a great impact on the computer. (From Baidu Baike)
System interaction with memory
At the operating system level, the minimum access unit for memory is a byte, or 8 bits.
A computer system is usually referred to as a 32-bit bus, which means that 32 bits (i.e., 4 bytes) can be read or written from memory at a time.
The memory region associated with the program
When we run a CPP program, the program is allocated a block of memory divided into five areas:
The stack
A storage unit allocated to a local variable of a function. After the function ends, the storage unit of the variable is automatically released, which is efficient and has limited space allocated.
The heap
A dynamic memory unit in a program created by new and freed by DELETE. If the user does not release the memory, the system automatically reclaims the memory when the program ends.
Free storage area
A dynamic memory unit created by malloc and freed by free, similar to a heap.
Global (static store)
Global and static variables occupy the same memory space.
Constant store
Store constants whose contents are not allowed to change.
Memory allocation of local variables
As an example, macOS builds from high to low.
System byte order
0x7ffeECf12740 to 0x7ffeecf12743 are allocated to int c, so how do I know 0x05 is 740 instead of 743?
The concept involved here is byte order. There are two ways to store these four bytes in memory: one way is to store the low-order bytes at the start location, which is called small-endian, and the other way is to store the high-order bytes at the start address, which is called big-endian (network byte order usually uses big-endian).
Knowing the small endian order, we can test our system, and the result is that our system (macOS) stores in small endian order. Therefore, 0x05 has 740 correctly.
Size of memory occupied by common type variables
Byte alignment
When we understood the above content, excitedly took out a memory related interview question to test the knife, but found that how to calculate the wrong answer! It’s not that the above is wrong, of course, but it’s because byte alignment is a favorite interview question.
In the computer storage system, data is stored in the unit of Byte. The space occupied by different data types is different, for example: int data occupies 4 bytes, char data occupies 1 Byte, short data occupies 2 bytes, and so on. Computer in order to quickly read and write data, by default the data is stored in an address starting position, such as: integer data (int), the default address is stored in the starting position, can be divided exactly by 4 (char) character data can be stored in any address location (divisible by 1), short integer (short) data is stored in the address can be divided exactly by 2 starting position. This is the default byte alignment.
Obviously the default alignment will waste a lot of space, such as the following structure:
struct student
{
char name[5];
int num;
short score;
}
Copy the code
This structure originally uses only 11 bytes of space, but since ints are 4-byte aligned by default, they are stored at the beginning of the address divisible by 4, that is, if name[5] is stored from 0, it takes up 5bytes, while num is stored from 8 bytes (offset). So sizeof student is equal to 16. So a few bytes in between are left idle. But it makes it easier for computers to read and write data quickly, a way of trading space for time. The data alignment is as follows:
|char|char|char|char|char|—-|—-|—-|——–int——–|–short–|—-|—-|
Dynamic memory management
One of the most common mistakes we make with dynamic memory is when we allocate memory for a member pointer variable in the constructor of a class and forget to release the memory for that member pointer variable when the object is destroyed.
The correct way to think about it is this:
class A(a) {
public:
A() {
p = new B(); // Request memory from the heap in the constructor} ~ (A) {delete p; // Memory should be actively freed in destructors
}
private:
B *p;
};
Copy the code
The resources
Explain how the operating system allocates memory
C++ memory allocation mechanism
Byte alignment in C++