Effective Memory Management
Advantages of using dynamic memory in a program:
1. dynamic memory can be shared between different objects and functions.
2. The size of the dynamically allocated memory space can be determined at runtime.
Prerequisites:
Int I = 7;
I is allocated on the stack.
Int * ptr;
Ptr = new int;
The pointer ptr is on the stack, and the ptr points to an internal stack.
Int ** handle;
Handle = new int *;
* Handle = new int;
The handle pointer is on the stack, the * handle pointer is on the stack, and the * handle points to the memory unit.
When memory is allocated using new, it is allocated on the heap. It returns a pointer to the allocated memory block. You need to use delete to display release. If the return value of new is ignored, or the pointer variable exceeds the scope, the memory will become an isolated unit, because you will no longer be able to access this memory.
Difference between malloc and new:
New not only allocates memory, but also calls the object constructor. Malloc only reserves a fixed-size memory and does not care about the object.
Difference between free () and delete:
When free () is used, the object's destructor is not called. Using delete will call the object's destructor and clear the object correctly.
Array:
As an experience: Do not use realloc (). This is dangerous because user-defined objects do not have a good experience with bitwise replication.
Delete an array:
When memory is allocated using the new (new []) used for the array, the delete (delete []) used for the array must be used to release the memory. In addition to releasing memory, this delete operation automatically removes the objects in the array.
Simple * mySimple = new Simple [4];
// Use mySimple
Delete [] mySimple;
Of course, only when the elements in the array are pure objects will the Destructor be called. If it is a pointer array, you still need to delete each element separately, just like allocating each element separately.
Simple ** mySimple = new Simple * [4];
For (int I = 0; I <4; I ++)
MySimple [I] = new Simple ();
// Use mySimple
For (int I = 0; I <4; I ++)
Delete mySimple [I];
Delete [] mySimple;
Multi-dimensional Stack Array:
Multi-dimensional heap array:
A heap-based multi-dimensional array is the same as a heap-based one-dimensional array. It can be accessed through pointers. The difference is that N-dimensional arrays require N-layer pointers.
The following code does not pass compilation,
Char ** board = new char [I] [j]; // error
Because heap-based multi-dimensional arrays do not work as stack-based multi-dimensional arrays. The memory allocated to it is not consecutive, so this method is incorrect. The correct method is: You must create a one-dimensional subscript Based on the heap array to allocate a continuous array. Each element of the array actually points to a pointer to another array, which stores the elements corresponding to the second-dimensional downlink.
Unfortunately, the compiler will not automatically allocate sub-array memory to you. This requires explicit allocation. When the sub-array is released, delete does not automatically delete the sub-array and needs to be released manually.
// New
Char ** myArray = new char * [xSize];
For (int I = 0; I <xSize; I ++)
MyArray [I] = new char [ySize];
// Delete
For (int I = 0; I <xSize; I ++)
Delete [] myArray [I];
Delete [] myArray;
Use Pointer:
Pointers are relatively easy to use, so they are easily abused. Since the pointer is only a memory address, it can be manually modified theoretically. You can even do the following:
Char * p = 7;
The code above creates a pointer to memory address 7, which may be a random garbage or a memory being used elsewhere in the application. If you use a memory area not allocated with new, the memory associated with the object will be damaged, so that the program will crash easily.
Use * To unreference the pointer.
Use & to get the address of the variable.
The forced conversion of pointer type:
Since the pointer is only a memory address, the pointer type is weak. The pointer to an XML document is the same as the pointer to an integer. Generally, c-style type forced conversion is used. The compiler can easily convert any type of pointer to another type.
Document * docPtr = getDocument ();
Char * charPtr = (char *) docPtr;
Static type forced conversion is more secure. The compiler rejects the forced conversion of static types to pointers to different data types.
Document * docPtr = getDocument ();
Char * charPtr = static_cast <char *> (docPtr); // error
If the two pointers of the forced conversion type actually point to the object associated with inheritance, the compiler allows the forced conversion of the static_cast type.
Const pointer: see the description of the const keyword.
In practice, pointer protection is rarely required. This is also irrelevant if the function can change the passed pointer value. Its function is only used within this function. For callers, the pointer still points to the original address. Set the pointer to const, which means that the usage of the pointer is more meaningful and does not provide much real protection. However, it is very common to protect the value pointed to by pointers to avoid rewriting shared data.
Array and pointer:
There is some overlap between the pointer and the array. The array allocated on the stack is referenced by a pointer pointing to the first element. Stack-based arrays are referenced using array syntax.
The stack-based array address is actually the address of 0th elements, and the array name is a pointer to 0th elements. But this pointer cannot be changed.
You can use functions to pass stack-based or heap-based arrays. When passing a stack-based array, the compiler will automatically degrade the array variable to a pointer to the array for processing. When passing a heap-based array, because the pointer to the array already exists, simply pass it to the function by value. If the function takes the array as the real parameter and changes the value in the array, this function actually modifies the original array ., Instead of an array copy. In fact, this is because C ++ considers efficiency, instead of copying an array, it degrades it to a pointer for processing, because it takes a lot of time to copy an array, it may also consume a large amount of memory space.
String:
C-style string:
Remember that there is a space '\ 0' behind the C-style string ';
String direct volume: the memory associated with the string direct volume is located in the read-only part of the memory.
Char * ptr = "hello"; // the string is directly assigned to the variable. ptr points to the read-only memory.
Ptr [1] = 'a'; // you cannot do this. It is a String constant and cannot be modified.
The security method is:
Const char * ptr = "hello"; // the string is directly assigned to the const variable.
Ptr [1] = 'a ';
You can also use the string quantity directly as the initial value of the stack-based character array, because the stack-based variables cannot reference the memory in other places under any circumstances, therefore, the compiler will copy the string directly to the stack-based Array Memory.
Char stackArray [] = 'hello ';
Char stackArray [1] = 'O'; // OK
Advantages and disadvantages of C-style strings:
Advantages: 1. It is relatively simple and uses the underlying basic character type and data structure.
2. The occupied space is small. If they are used correctly, they only need to occupy the actually needed memory space.
3. More underlying, so it can be easily processed and copied as the original memory.
4. programmers can better understand.
Disadvantages:
1. The existence of memory bugs is intolerable and is greatly affected.
2. It is useless to make full use of the object-oriented features of c ++.
3. The auxiliary functions provided are poorly named and sometimes confused.
4. Ask the programmer to understand the underlying representation of the string.
String of C ++:
Based on the magic of operator overloading, string uses + to connect two strings, = to assign values (will copy strings), = to compare, [] to access a single character.
You can use c_str () to convert C ++ string to a C-style string.
Low-level memory operations:
One of the main advantages of C ++ is that it does not need to worry about memory issues. If the Code uses an object, you only need to ensure that each class can properly manage its own memory. By constructing and revoking an object, the compiler will tell you what to do and help you manage the memory. However, some applications may encounter this situation, that is, the memory needs to be used at a low level.
Pointer operation: the pointer plus 1 is a unit that moves the Pointer Forward. A pointer of the same type minus the number of elements between two pointers.
If you compile a character string into uppercase, char * toCaps (const char * inString );
If you only want to convert the strings after myStr to uppercase, you can call toCaps (myStr + 5) in this way );
Custom memory management: In most cases, the built-in memory allocation function is sufficient. However, if resources are insufficient, you can manage the memory by yourself. Managing memory by yourself may reduce resource overhead. When using new to allocate memory, the program also needs to keep a small space to record how much memory space has been allocated. In this way, the appropriate amount of memory can be released when the delete operation is called. For most objects, this overhead is much smaller than the allocated memory, so there is no big difference. However, for small objects or programs with a large number of objects, this overhead may have a great impact. When you manage the memory by yourself, you know the size of each object in advance, so you can avoid this overhead. For a large number of small objects, compared with the new and delete methods, this will bring a lot of difference.
Garbage Collection: in an environment that supports garbage collection, programmers rarely need to explicitly release memory associated with objects. Instead, a low-priority background task is responsible for monitoring the memory status and clearing the memory that it deems unnecessary.
Unlike java, garbage collection is not used as a built-in function in C ++. Most C ++ programs manage the memory at the object level through new and delete. It is not impossible to implement garbage collection in C ++. However, to release the memory from the task, it may bring new problems.
A Method of garbage collection is called marking and cleaning. In this way, the garbage collector periodically checks every pointer in the program and marks that the referenced memory is still in use. At the end of the loop, the memory that is not marked is considered to be in use and can be released.
Steps to complete:
1. register all pointers with the Garbage Collector so that you can easily scan the entire pointer list.
2. Let all objects derive a mixed class (such as GarbageCollectible), which allows the Garbage Collector to mark the object as being used.
3. Ensure that the pointer is not modified when the garbage collector is running to protect concurrent access to the object.
This simple garbage collection method requires the programmer to be very careful. Compared with delete, this method may cause errors more easily. C ++ has tried to establish a safe and easy mechanism for garbage collection, but even in C ++, it does provide an ideal garbage collection implementation, not necessarily applicable to all applications.
Garbage collection has the following Disadvantages:
1. When the Garbage Collector actively runs, the program may slow down.
2. If the program allocates a large amount of memory, the Garbage Collector may not be able to keep up with this speed.
3. If the Garbage Collector has a bug or thinks that a discarded object is still in use, it may cause irreparable Memory leakage.
Object pool: analysis is performed later.
Function pointer: each function is indeed located at a specific address. In C ++, functions can be used as data. In other words, the address of a function can be used as a parameter, just like variables.
The function pointer determines the function type based on the parameter type and the compatible function return type. The easiest way to use function pointers is to use the typedef mechanism to assign a function name to a group of functions with given features. The following declares a type YesNoFcn, which represents a pointer pointing to any function of the bool type with two int parameters.
Typedef bool (* YesNoFcn) (int, int );
Now that a new type is available, you can compile a function that takes YesNoFcn as the parameter.
Void findMatches (int values1 [], int values2 [], int numValues, YesNoFcn inFunction)
{
For (I = 0; I <numValues; I ++)
If (inFunction (values1 [I], values [2])
Cout <"match! ";
Else cout <"not match! ";
Cout <endl;
}
Bool intEqual (int inItem1, int inItem2)
{
Return inItem1 = inItem2;
}
// Call
Int a [2] = {1, 2}, B [2] = {1, 3 };
FindMatches (a, B, 2, & intEqual );
Common memory traps:
1. Insufficient string space allocation
Char str [3] = "yes"; // error has a '\ 0'
2. Memory leakage
If the memory is allocated but you forget to release it, memory leakage may occur. (The free valgrind tool can be used to track memory usage ).
You can also use smart pointers to avoid Memory leakage. That is to say, if we put everything in the stack, this can avoid most memory-related problems. The stack is safer than the heap because the stack variables are automatically revoked and cleared once they exceed the scope. Smart pointers combine the security of stack variables and the flexibility of stack variables. It is an object with correlated pointers. When the smart pointer exceeds the scope, the associated pointer is deleted. Essentially, a stack object is encapsulated in a stack-based object.
The C ++ standard template library contains the basic implementation of a smart pointer. It is called auto_ptr. You can store dynamically allocated objects in stack-based auto_ptr instances instead of pointers. When auto_ptr is out of scope, the memory associated with auto_ptr is cleared.
Void leaky ()
{
Simple * mySimple = new Simple ();
MySimple-> go ();
} // The memory is not explicitly released and the object is deleted.
Void leaky ()
{
Auto_ptr <Simple> mySimple (new Simple );
MySimple-> go ();
}
Smart pointers can also use *-> like standard pointers to release references.
3. Secondary deletion and Invalid Pointer
Once delete is used to release the memory associated with the pointer, other parts of the program can use this memory. However, nothing can prevent you from trying to continue using this pointer. Secondary deletion is also a problem. If you use delete again on the pointer, the program may release the memory that has been assigned to another object.
Many memory leak check programs (such as valgrind) also check secondary deletion and use of released objects.
4. Cross-border access pointer
The buffer overflow error is often caused by out-of-bounds memory write bugs. Such bugs have been exploited by powerful viruses and worms. You can also use only one part of the memory to overwrite them. To inject code into a running program.
Fortunately, many memory detection tools can also detect buffer overflow errors. Besides, although there are a lot of related bugs when writing C-style strings and arrays to content, using advanced constructs such as C ++ strings and vectors can help prevent such bugs.
From my dream pursued by me