Introduction
For anyone who uses the C language, if they ask what is the biggest headache of the C language, many may say yes.Pointer and Memory leakage. This does consume most debugging time for developers. Pointer and memory leaks seem daunting for some developers, but once you understand the basics of pointers and their associated memory operations, they are the most powerful tool in the C language.
This article will share with you the secrets developers should know before using pointers for programming. This article includes:
- Pointer operation type that causes Memory Corruption
- Checkpoints that must be considered when dynamic memory allocation is used
- Scenarios that cause memory leakage
If you know in advance where an error may occur, you can avoid traps and eliminate most of the issues related to pointers and memory.
Address: http://www.cnblogs.com/archimedes/p/c-point-memory-leak.html.
Where can an error be reported?
Several problems may occur, which may cause problems after generation. When processing pointers, you can use the information in this article to avoid many problems.
Common memory errors and their countermeasures are as follows:
1. Memory Allocation failed, but it was used
New programmers often make this mistake because they do not realize that memory allocation will fail. A common solution is to check whether the pointer is NULL before using the memory. If the pointer p is a function parameter
Use assert (p! = NULL. If you use malloc or new to apply for memory, you should use if (p = NULL) or if (p! = NULL.
2. Although the memory allocation is successful, it is referenced before initialization.
There are two main causes for this mistake: first, there is no idea of initialization; second, the default initial values of the memory are all zero, resulting in incorrect reference values (such as arrays ).
There is no uniform standard for the default initial values of the memory. Although sometimes it is zero, we prefer to trust it without any trust. Therefore, no matter which method is used to create an array, do not forget to assign the initial value, even if it is zero.
Value cannot be omitted.
3. The memory has been allocated successfully and initialized, but the operation has crossed the memory boundary.
For example, when an array is used, the subscript "more than 1" or "less than 1" is often performed. Especially in for loop statements, the number of loops is easy to make a mistake, resulting in array operations out of bounds.
4. Forgot to release the memory, causing memory leakage
A function containing such errors loses a piece of memory every time it is called. At the beginning, the system had sufficient memory and you could not see the error. Once a program suddenly died, the system prompts: memory is exhausted.
Uninitialized Memory
In this example,p
10 bytes have been allocated. These 10 bytes may contain junk data, as shown in 1.
char *p = malloc ( 10 );
Figure 1. Junk data
Ifp
Before a value assignment, a code segment tries to access it, and may obtain the spam value. Your program may have unpredictable behavior.p
It may have a value that your program never expected.
A good practice is to always work togethermemset
Andmalloc
, Or usecalloc
.
char *p = malloc (10);memset(p,’\0’,10);
Now, even if the same code segment triesp
Access it before value assignment, and the code segment can be correctly processedNull
Value (the value that should be valid in ideal cases), and then has the correct behavior.
Memory coverage
Becausep
10 bytes have been allocated. If a code snippet attemptsp
If an 11-byte value is written, the Operation will automatically "eat" one byte from another location without telling you. Let's assume that the pointerq
Memory.
Figure 2. Original q content
Figure 3. Overwrite q content
Result, pointerq
Will have unexpected content. Even if your module is properly encoded, it may be incorrect because a co-located module performs some memory operations. The following sample code snippet also describes this scenario.
char *name = (char *) malloc(11); // Assign some value to namememcpy ( p,name,11); // Problem begins here
In this example,memcpy
Operation attempts to write 11 bytesp
The latter is allocated with only 10 bytes.
As a good practice, every time you write a value to a pointer, make sure that the number of available bytes and the number of written bytes are checked. Generally,memcpy
The function will be a checkpoint for this purpose.
Memory read out of bounds
Overread refers to the number of bytes read more than the expected bytes. This issue is not very serious and will not be detailed here. The following code provides an example.
char *ptr = (char *)malloc(10);char name[20] ;memcpy ( name,ptr,20); // Problem begins here
In this example,memcpy
Operation attempt fromptr
Read 20 bytes, but the latter is allocated 10 bytes. This also causes unwanted output.
Memory leakage
Memory leakage may be annoying. The following list describes some scenarios that cause memory leakage.
char *memoryArea = malloc(10);char *newArea = malloc(10);
This value is assigned to the memory position shown in figure 4 below.
Figure 4. memory location
memoryArea
AndnewArea
Each of the 10 bytes is allocated, as shown in figure 4. If someone executes the following statement (the pointer is assigned a value again )......
memoryArea = newArea;
It will certainly cause you trouble in the subsequent stages of the module development.
In the preceding Code statementmemoryArea
Assign a pointernewArea
Pointer. Result,memoryArea
The previously pointed memory location becomes isolated, as shown in Figure 5 below. It cannot be released because there is no reference pointing to this location. This results in 10 bytes of Memory leakage.
Figure 5. Memory leakage
Before assigning values to pointers, make sure that the memory location is not isolated.
If free is calledmemoryArea
, ThennewArea
The pointer also becomes invalid.newArea
The previously pointed memory location cannot be released because there is no pointer to this location. In other words,newArea
The memory location pointed to is changed to isolated, resulting in Memory leakage.
When a structured element is released and the element contains a pointer to the dynamically allocated memory location, the sub-memory location should be traversed first (in this examplenewArea
), And start releasing from there, and then traverse back to the parent node.
The correct implementation here should be:
free( memoryArea->newArea);free(memoryArea);
- Incorrect processing of returned values
Sometimes, some functions return a reference to the dynamically allocated memory. Tracking the memory location and correctly processing it becomescalling
Function responsibilities.
char *func( ){ return malloc(20); // make sure to memset this location to ‘\0’…}void callingFunc( ){ func ( ); // Problem lies here}
In the preceding example,callingFunc()
Functionfunc()
The function call does not process the return address of the memory location. Result,func()
The 20-byte block allocated by the function is lost, resulting in Memory leakage.
Return
A large amount of dynamic memory allocation may exist during component development. You may forget to keep track of all pointers (pointing to these memory locations), and some memory segments are not released and are still allocated to the program.
Always track all memory allocations and release them whenever appropriate. In fact, you can develop a mechanism to track these distributions, such as retaining a counter in the linked list Node itself (but you must also consider the additional overhead of this mechanism ).
Access a null pointer
It is very dangerous to access a null pointer because it may cause your program to crash. Always make sure that youNoAccess the NULL pointer.
Summary
This article discusses several traps that can be avoided when dynamic memory allocation is used. To avoid memory problems, good practices are as follows:
- Always used in combination
memset
And malloc, or always usecalloc
.
- When writing a value to the pointer, make sure that the number of available bytes and the number of written bytes are checked.
- Before assigning values to pointers, make sure that no memory location is isolated.
- Whenever a structured element is released (and the element contains a pointer to the dynamically allocated memory location), the sub-memory location should be traversed and released from there, and then traverse back to the parent node.
- Always correctly handle the return value of the function referenced by the dynamically allocated memory.
- Each
malloc
There must be a corresponding free.
- Make sure that you are not accessing the NULL pointer.