In C ++ and C ++ language development, pointers and memory have always been the focus of learning. Because the C language is a low-level low-level language, it provides a large number of methods for direct memory operation. This aspect maximizes the flexibility of the program and also lays many hidden dangers for bugs.

Therefore, in any case, we must have a clear understanding of memory.

1. Internal distribution

The 32-bit operating system supports continuous access to 4GB of memory, but usually divides the memory into two 2GB spaces. Each process can use up to 2GB of private memory (0x00000000-0x7FFFFFFF) while running. In theory, the following large arrays are supported:

char szBuffer [2 * 1024 * 1024 * 1024];

Of course, because the program still has code segments, temporary variable segments, dynamic memory applications, etc. during actual operation, it is actually impossible to use such a large array.

As for the high-end 2GB memory address (0x80000000-0xFFFFFFFF), the operating system is generally reserved for internal use, that is, used by the operating system kernel code. On Windows and Linux platforms, some dynamic link libraries (Windows dll, Linux so) and ocx controls, etc., because they are cross-process services, generally run in the high 2GB memory space.

As you can see, each process can see its own 2GB memory and the system's 2GB memory, but different processes cannot see each other. Of course, the operating system does a lot of work at the bottom, such as virtual memory swapping on the disk (see the title below), dynamic mapping of different memory blocks, and so on.

Two, virtual memory

The basic idea of ​​virtual memory is to use cheap but slow disks to expand fast but expensive memory. At a certain moment, the contents of the virtual memory segment that the program actually needs to use are loaded into physical memory. When the data in the physical memory has not been used for a period of time, they may be transferred to the hard disk, and the saved physical memory space is used to load other data that needs to be used.

In the process of process execution, the operating system is responsible for specific details, so that each process thinks that it has exclusive access to the entire address space. This illusion is realized through "virtual memory". All processes share the physical memory of the machine, and use the disk to save data when the memory is used up. As the process runs, data moves back and forth between disk and memory. The memory management hardware is responsible for translating virtual addresses into physical addresses and letting a process always run in the real memory of the system. Application programmers only see the virtual addresses and do not know that their processes switch back and forth between disk and memory.

In terms of potential possibilities, all memory related to the process will be used by the system. If the process may not run immediately (maybe its priority is low or it may be in a sleep state), the operating system can temporarily Retrieve all the physical memory resources allocated to it, and back up all relevant information of the process to the disk.

A process can only operate on pages located in physical memory. When the process references a page that is not in physical memory, the MMU will generate a page fault. The memory responds to this matter and determines whether the reference is valid. If it is invalid, the kernel sends a "segmentation violation" signal to the process. The kernel retrieves the page from the disk and swaps it into memory. Once the page enters the memory, the process is unlocked and can be re-run-the process itself and I don't know if it used to wait for a while because of the page-in event.

Third, the use of memory

For programmers, the most important thing is to understand the meaning of private memory space between different processes. C and C ++ compilers divide private memory into three blocks: base stack, floating stack, and heap. As shown below:

(1) Base stack: also called static storage area, which is the memory that the compiler must use during compilation, such as the code segment of the program, static variables, global variables, and const constants.

(2) Floating stack: In many books, it is called "stack", that is, the program starts to run. With the execution of a function or an object, the internal variables of the function and the internal member variables of the object start to occupy memory dynamically. The floating stack generally has a life cycle At the end of the function or object destruction, the corresponding floating stack space is removed. This part of the content always changes, and the memory footprint is not fixed, so it is called the floating stack.

(3) Heap: Both C and C ++ languages ​​support dynamic memory application, that is, you can apply for memory freely during the program runtime, and this part of memory is applied in the heap space. The heap is located at the very top of 2GB and is allocated from top to bottom. This is to avoid mixing with the floating stack and is not easy to manage. We use malloc and new are the memory applied from the heap space, new has more object support than malloc, and can automatically call the constructor. In addition, new creates objects whose member variables are located in the heap.

Let's look at an example:

const int n = 100; void Func (void)

{

char ch = 0;

char * pBuff = (char *) malloc (10);

// ...

}

If this function runs, where n is a global static variable, located on the base stack, ch and pBuff are two internal variables of the function, ch is on the floating stack, and the memory area allocated by malloc pointed to by pBuff is on the stack.

In memory understanding, the most famous example is the parameter passing when the thread starts.

When a function starts a thread, it is often necessary to pass parameters to the thread, but the thread is started asynchronously, that is, it is likely that the startup function has exited, and the thread function has not officially started running. Therefore, you must never use the internal variables of the startup function to give Thread pass parameters. The reason is simple. The internal variables of the function are on the floating stack, but when the function exits, the floating stack is automatically removed and the memory space has been released. When the thread starts, querying the variable according to the given parameter pointer is actually reading an invalid memory area, and the program will crash.

then what should we do? We should directly use the malloc function to allocate a memory area to the parameters that need to be passed, pass the pointer to the thread, use it after the thread is received, and finally release it when the thread exits.

Let's look at an example:

// This structure is the parameter table typedef struct _CListen_ListenAcceptTask_Param_

{

Linux_Win_SOCKET m_nSocket;

// Other parameters ...}} SCListenAcceptTaskParam;

// Custom writing, after setting the structure, immediately declare the size of the structure to provide convenience for subsequent malloc const ULONG SCListenAcceptTaskParamSize = sizeof (SCListenAcceptTaskParam);

// Receive a connection request here, apply for a parameter area, and bring key information into the parameter area to help subsequent threads work.

bool CListen :: ListenTaskCallback (void * pCallParam, int & nStatus)

{

// Normal function logic ...

// Assuming that s is the socket that was accepted, it needs to be passed into the subsequent thread to work

// Prepare a parameter area here and apply from the far stack

SCListenAcceptTaskParam * pParam = (SCListenAcceptTaskParam *) malloc (SCListenAcceptTaskParamSize);

// Assign value to the parameter area

pParam-> m_nSocket = s;

// Start the thread here, pass pParam to the thread ...

// Normal function logic ...

}

// This is a thread function, which is responsible for processing the socket received above

bool CListen :: ListenAcceptTask (void * pCallParam, int & nStatus)

{

// The first sentence is to force the pointer type conversion to obtain the parameter area passed in by the outside world

SCListenAcceptTaskParam * pParam = (SCListenAcceptTaskParam *) pCallParam;

// Normal function logic ...

// The work that must be done before exiting to ensure that resources are not leaked

close (pParam-> m_nSocket); // Close the socket

free (pCallParam); // parameter area of ​​free

// ...…

}

Four, memory bug

Random misuse of memory and pointers will cause a lot of bugs. Programmers should maintain a high degree of sensitivity and vigilance in the use of memory and use memory resources carefully.

The most likely bugs when using memory are:

(1) Bad pointer value error: use the pointer to refer to memory before assigning the pointer, or transfer a bad pointer to the library function. The third cause of bad pointers is to release the pointer and then access its contents. You can modify the free statement and set it to a null value after the pointer is released.

free (p); p = NULL;

In this way, if the pointer continues to be used after the pointer is released, at least the program can dump the information before terminating.

(2) Overwrite error: write data across the array boundary, write data outside the ends of the dynamically allocated memory, or rewrite some heap management data structures (writing data in the area before dynamically allocated memory is easy This happens)

p = malloc (256); p [-1] = 0; p [256] = 0;

(3) Error caused by pointer release: release the same memory block twice, or release a memory that has not been allocated with malloc, or release memory that is still in use, or release an invalid pointer. A very common error related to freeing memory is to iterate a linked list in a loop like for (p = start; p = p-> next) and use the free (p) statement in the loop body. In this way, in the next loop iteration, the program will dereference the pointer that has been released, resulting in unpredictable results.

We can iterate like this:

struct node * p, * tart, * temp; for (p = start; p; p = temp)

{

temp = p-> next;

free (p);

}

CT For Management Terminal Unit

Our company`s current transformers have high precision,wide range,small volume and good linearity that can be used to the field of electronic watt-hour meter, electric energy metering, electronic detection.

Performance

●Power frequency insulation strength:The insulation between the primary winding and the secondary winding and the ground part of the CT can bear 4kV power frequency voltage for 1minute

●Interturn insulation strength:The secondary open circuit, the primary winding through the rated current 1min, no inter-turn damage in the transformer

●The deviation is better than the industry standards and national standards

Management Terminal Unit Ct,New Design Current Transformer,Zero Phase Ct,Useful Residual Ct

Anyang Kayo Amorphous Technology Co.,Ltd. , https://www.kayoamotech.com