Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to deeply understand the pointer of C language

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article to share with you is about how to deeply understand the C language pointer, Xiaobian feel quite practical, so share to everyone to learn, I hope you can read this article after some harvest, not much to say, follow Xiaobian to see it.

origin

Before I read a sentence on Zhihu, the pointer is the essence of C, and it is also a barrier for beginners. In other words, memory management is the essence of C, C/C++ can deal directly with the OS, from a performance point of view, developers can flexibly allocate and release memory according to their actual use scenarios. Although smart pointers have been introduced in C++ since C++11, although they can be largely avoided, they are still not completely avoided. One of the most important reasons is that you cannot guarantee that other people in the group will not use pointers, and you cannot guarantee that cooperative departments will not use pointers.

So why do pointers exist in C/C++?

This starts with the memory layout of the process.

process memory layout

The above figure shows the memory layout of the 32-bit process. From the above figure, it mainly contains the following blocks:

Kernel space: Used by the kernel, where kernel code and data are stored

stack: This is what we often call a stack, used to store automatic variables

mmap: Also known as a memory map, it is used to allocate address space in the process virtual memory address space and create a mapping relationship with physical memory.

heap: is what we often call heap, dynamic memory allocation is all on heap

bss: Contains all uninitialized global and static variables, all variables in this segment are initialized by 0 or null pointer, program loader allocates memory for BSS segment when loading program

ds: Initialized data block

Contains explicitly initialized global variables and static variables

The size of this segment is determined by the size of the value in the program source code and does not change at runtime

It has read and write permissions, so variable values for this segment can be changed at runtime

This section can be further divided into an initialization read-only area and an initialization read-write area

text: also known as text segment

This section contains the binary file of the compiled program.

This section is a read-only section that prevents the program from being accidentally modified

This segment is shareable, so for frequently executed programs such as text editors, only one copy is needed in memory

Since this article focuses on memory allocation, the following content only relates to stack and heap.

stack

Stack A contiguous block of memory on which memory allocations are performed. The compiler already knows the memory size to allocate when compiling, and when calling the function, its internal traversal allocates memory on the stack; when the function call is terminated, the internal variables are released, and then the memory is returned to the stack.

class Object { public: Object() = default; // ....}; void fun() { Object obj; // do sth}

In the above code, obj is allocated on the stack, and when it is out of the fun scope, it will automatically call the destructor of Object to release it.

As mentioned earlier, local variables are destructed and memory is freed at the end of the scope (such as function scope, block scope, etc.). Because allocation and deallocation are in exactly the opposite order, the FILO feature can be used, and C++ implementations generally use the call stack to allocate local variables (but not the standard requirement).

Because memory allocation and deallocation on the stack is a push and pop process (just a pointer movement process for the compiler), the stack is much faster than memory allocation on the heap.

Although the access speed of stack is faster than heap, each thread has its own stack, and the objects on the stack cannot be accessed across threads, which determines that the stack space is limited. If the stack space is too large, then in large programs, dozens or even hundreds of threads, the light stack space consumes RAM, which leads to the heap available space becoming smaller, affecting the normal operation of the program.

set

On Linux systems, you can view stack size with the following command:

ulimit -s10240

On the author's machine, the output of executing the above command is 10240(KB) or 10m, and the stack size can be modified by shell command.

ulimit -s 102400

The stack space can be temporarily modified to 100m by the above command, which can be done by the following command:

/etc/security/limits.conf Allocation

static allocation

Static allocation is done by the compiler, if local variables and function parameters, etc., are allocated at compile time.

void fun() { int a[10];}

In the above code, a accounts for 10 * sizeof(int) bytes, which is calculated directly at compilation time, and directly pushed into and pulled out of the stack at run time.

dynamic allocation

Many people may think that dynamic allocation exists only on the heap, and only static allocation is possible on the stack. In fact, this view is wrong, the stack also supports dynamic allocation, the dynamic allocation is allocated by the alloca() function. Stack dynamic allocation and heap are different, memory allocated by alloca() function is released by compiler, out of order manual operation.

characteristics

Fast allocation speed: allocation size is done by the compiler in the compiler

No memory fragmentation: stack memory allocation is sequential, pushed and popped in FIFO fashion

Size limitation: Stack size depends on operating system

Restricted access: Access can only be made within the current function or scope

pile

Heap is a form of memory management. Memory management is a very complex business for operating systems because, firstly, memory is large, and secondly, memory requirements are irregular in time and block size (there are dozens or even hundreds of processes running on the operating system, and these processes may request or release memory at any time, and the memory block size requested and released is arbitrary).

Heap this memory management mode is characterized by freedom (at any time to apply, release at any time, size block arbitrary). Heap memory is allocated by the operating system to the heap manager (a piece of code in the operating system, belonging to the memory management unit of the operating system) to manage, the heap manager provides the corresponding interface_sbrk, mmap_, etc., but the interface is often called by the runtime library, that is, the runtime library performs heap memory management, and the runtime library provides the malloc/free function to be called by developers to use heap memory.

distribution methods

As we understand it, since memory allocation is done at runtime and the size of the allocation is not known until runtime, the heap only supports dynamic allocation, and the behavior of memory request and release is operated by the developer itself, which is easy to cause what we call memory leakage.

characteristics

Variable is process-scoped, meaning all threads within a process can access the variable.

There is no memory size limit, this is actually relative, but there is no limit relative to the stack size, in fact, it is ultimately limited to RAM.

Access is slower than stack

memory fragmentation

Memory management by developers, that is, memory application and release are operated by developers

Difference between stack and heap

Understanding the difference between heap and stack will be very useful to us in the development process. Combined with the above content, summarize the difference between the two.

For stack, it is automatically managed by compiler, without manual control; for heap, release work is controlled by programmer, easy to generate memory leak

Space sizes vary

Generally speaking, in 32-bit systems, heap memory can reach 4G space, from this point of view heap memory is almost no limit.

For the stack, there is generally a certain space size, generally depending on the operating system (can also be manually set)

whether or not it can produce fragments differently.

For heap, frequent memory allocation and deallocation will inevitably lead to discontinuity of memory space, resulting in a large number of fragments, which will reduce program efficiency.

For stacks, memory is continuous, and requests and releases are instruction moves, similar to pushing and popping in data structures.

Different growth directions

For the heap, the growth direction is upward, that is, toward the direction of memory address increase.

For the stack, its growth direction is downward, and it grows in the direction of memory address reduction.

Different distribution methods

Heaps are dynamically allocated, such as our common malloc/new, while stacks are statically allocated and dynamically allocated.

Static allocation is done by the compiler, such as allocation of local variables, while dynamic allocation of stacks is done through the alloca() function.

The dynamic allocation of the stack is released by the compiler, while the dynamic allocation of memory on the heap must be released by the developer.

Distribution efficiency varies

The stack has a special register allocated by the operating system to store the address of the stack, and there are special instructions for stack pushing and stack pulling, which determines the stack efficiency.

Heap memory application and release are specially provided by runtime libraries, which involve complex logic, application and release efficiency is lower than stack

Up to this point, the basic characteristics of stack and heap, as well as their respective advantages and disadvantages, use scenarios have been analyzed, here to give developers a suggestion, can use the stack, try to use the stack, on the one hand because the efficiency is higher than the heap, on the other hand, memory application and release by the compiler to complete, so as to avoid a lot of problems.

extended

Finally to this section, in fact, the above said so much, are for this section to do the groundwork.

In the previous content, we compared the stack and heap, although the stack efficiency is relatively high, and there is no memory leak, memory fragmentation, etc., but due to its own limitations (can not be multi-threaded, limited size), so in many cases, still need to be on the heap memory.

Let's start with a code:

#include #include int main() { int a; int *p; p = (int *)malloc(sizeof(int)); free(p); return 0;}

The above code is very simple, there are two variables a and p, the type is int and int *, where a and p are stored on the stack, the value of p is a block address on the heap (in the above code, the value of p is 0x1c66010), the above code layout is shown below:

The above is how to deeply understand the pointer of C language, Xiaobian believes that some knowledge points may be seen or used in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report