First part C + + memory allocation
One. About memory
1. Memory allocation mode
There are three ways to allocate memory:
(1) Distribution from the static storage area. The memory is already allocated when the program is compiled, which exists throughout the running of the program.
such as global variables, static variables.
(2) created on the stack. When the function is executed, the storage units of local variables within the function can be created on the stack, and these save at the end of the function execution
The storage unit is automatically released. Stack memory allocation operations are placed within the processor's instruction set, which is highly efficient, but allocates a limited amount of memory.
(3) Allocation from the heap, also known as dynamic memory allocation. The program at run time with malloc or new request any amount of memory, the programmer from
You are responsible for releasing memory when free or delete. The lifetime of dynamic memory is determined by us and is very flexible to use, but the problem is the most.
2. Memory Usage Error
A memory error is a very troublesome thing to do. The compiler cannot automatically discover these errors, which are usually captured when the program is running.
Most of these errors do not have obvious symptoms, the hidden, increase the difficulty of error. Sometimes the user is angry to find you, the program is not
Any problem, you go, the mistake again attack. Common memory errors and their countermeasures are as follows:
* The memory allocation was unsuccessful, but it was used.
Novice programmers often make this mistake because they are unaware that memory allocations will be unsuccessful. A common workaround is to check before using memory
Whether the pointer is null. If you are using malloc or new to request memory, you should use if (p==null) or if (P!=null) for error proofing.
* The memory allocation was successful, but it was referenced without initialization.
There are two main causes of this error: one is the idea that there is no initialization; the second is to mistakenly assume that the default initial value of memory is zero, leading to the reference initial value
Errors (such as arrays). What is the default initial value of memory and there is no uniform standard, although sometimes zero value, we would rather believe that all
Believable it has. So no matter how you create an array, do not forget to assign an initial value, even if it is assigned 0 values can not be omitted, do not bother.
* The memory allocation was successful and initialized, but the operation crossed the bounds of the memory.
For example, when using an array, the subscript "more 1" or "less 1" is often taken place. Especially in the For Loop statement, the number of loops is easily mistaken, causing the array operation to cross over.
* Forgot to release memory, resulting in memory leaks.
A function that contains this error loses a piece of memory every time it is called. The system has plenty of memory at first, and you can't see the error. Once in a while
The program suddenly dies, the system prompts: the memory is running out.
Dynamic memory application and release must be paired, in the program malloc and free usage must be the same, otherwise there must be a mistake
(New/delete in the same vein).
* Freed up memory but continues to use it.
There are three kinds of situations:
(1) The object invocation relationship in the program is too complex to find out whether an object has freed up memory and should be
The design data structure, fundamentally solves the object management the chaos situation.
(2) The return statement of the function was incorrectly written, noting that the "pointer" or "reference" point to "stack memory" is not returned because the memory
The number of bodies is automatically destroyed at the end.
(3) When memory is freed with free or delete, the pointer is not set to null. Causes the "wild pointer" to be generated.
After rule 1 requests memory with malloc or new, you should immediately check that the pointer value is NULL. Prevent using memory with pointer value NULL
Rule 2 Do not forget to assign an initial value to an array and dynamic memory. Prevents unused memory from being initialized as a right value.
Rule 3 avoids the scaling of arrays or pointers, especially beware of "more than 1" or "less 1" operations.
"Rule 4" dynamic memory requests and releases must be paired to prevent memory leaks.
When rule 5 frees memory with free or delete, it immediately sets the pointer to NULL to prevent the "wild pointer" from being generated.
Two. Detailed New,malloc,globalalloc
1. New
The new and delete operators are used to dynamically allocate and revoke memory operators
New usage:
1> open a single variable address space
1) New int; Opens a storage space for the array, returning an address to the storage space. int *a = new
int assigns the address of an int type to the integer pointer A.
2 int *a = new int (5) acts as above, but at the same time assigns an integer value of 5
2> Open Array Space
One-dimensional: int *a = new INT[100]; Create an integer array space of size 100
General usage: new type [initial value]
Delete usage:
1> int *a = new int;
Delete A; Free space for a single int
2>int *a = new Int[5];
delete [] A; Frees int array space
To access the structure space opened by new, you cannot go directly through the variable name, only through the assigned pointer.
Use new and delete to dynamically open up and undo the address space. If you run out of a variable (typically a temporarily stored array) at the time of the program,
The next time you need to reuse, but you want to save the initialization of the Kungfu, you can start each time to open a space, after the use of the undo it.
2. malloc
Prototype: extern void *malloc (unsigned int num_bytes);
Usage: #i nclude <malloc.h> #i nclude <stdlib.h>
Function: Allocate a block of memory with a length of num_bytes bytes
Note: Returns a pointer to the allocated memory if the assignment succeeds, or null if the null pointer is returned.
When memory is no longer in use, you should use the free () function to release the memory block.
The syntax for malloc is: pointer name = (data type *) malloc (length), (data type *) represents a pointer.
Description: malloc allocates the memory space for the specified size byte to the system request. The return type is the void* type. void* indicates an indeterminate type
The pointer. C,c++ stipulates that the void* type can be cast to any other type of pointer.
The working mechanism of the malloc () function
The substance of the malloc function now, it has a so-called idle list that connects the available chunks of memory to a long listing. Call malloc
function, it looks for a block of memory along the join table that is large enough to satisfy the user's request. Then, divide the memory block in two (a large
Small is equal to the size of the user request, and the other size is the remaining byte. Next, the memory assigned to the user is passed to the user, and
Return the remaining piece (if any) to the connection table. When the free function is invoked, it connects the memory blocks freed by the user to the idle chain. To
Finally, the free chain will be cut into a lot of small memory fragments, if the user requests a large memory fragment, then the idle chain may not be able to
To meet the user requirements of the fragment. As a result, the MALLOC function requests a delay and starts rummaging through the free chain to check each memory fragment
To organize and merge the adjacent small free blocks into larger chunks of memory.
The difference between new and
As you can see from the function declaration. malloc and new are at least two different: new returns a pointer of the specified type and can automatically calculate the desired
To size. Like what:
int *p;
p = new int; The return type is the int* type (integer pointer) and the allocation size is sizeof (int);
Or:
Int* Parr;
Parr = new int [100]; The return type is the int* type (integer pointer), and the allocation size is sizeof (int) * 100;
malloc, however, must be calculated by us for the number of bytes, and will be forcibly converted to the actual type of pointer after the return.
int* p;
p = (int *) malloc (sizeof (int));
First, the malloc function returns the void * type if you write: p = malloc (sizeof (int)); The program cannot be compiled,
Error: "Cannot assign void* to int * type variable". So you must pass the cast by (int *).
Second, the function's argument is sizeof (int), which indicates the size required for an integer data. If you write:
int* p = (int *) malloc (1);
The code can also be compiled, but in fact allocates only 1 bytes of memory space, and when you deposit an integer into it, there will be 3 bytes without
Home can return, and directly "live in the neighbor's house"! The result is that the contents of the original data in the back of the memory are all emptied.
3. GlobalAlloc
VC in about Globalalloc,globallock,globalunlock
The GlobalAlloc function is called to allocate a chunk of memory that returns the allocated memory handle.
Call the GlobalLock function to lock a block of memory that takes a memory handle as a parameter and then returns a pointer to the locked block of memory. You can use this pointer to read and write memory.
Call the GlobalUnlock function to unlock previously locked memory, which invalidates the pointer to the memory block.
Call the GlobalFree function to free the memory block. You must pass the function a memory handle.
GlobalAlloc
Description
Allocating a global memory block
return value
Long, which returns the global memory handle. Zero indicates failure. Will set GetLastError
Parameter table
Parameter type and description
Wflags Long, a constant flag that defines the allocated memory type, as follows:
Gmem_fixed allocate a block of fixed memory
Gmem_moveable allocate a removable memory block
Gmem_discardable allocate a disposable memory block
Gmem_nocompact Heap does not accumulate during this function call
No memory blocks are discarded during gmem_nodiscard function calls
Gmem_zeroinit the newly allocated memory blocks are all initialized to 0
Dwbytes Long, number of characters to assign
GlobalLock
Function Description: Locks a global Memory object, returns a pointer to the first byte of the object
Function Prototypes:
LPVOID GlobalLock (Hglobal hmem)
Parameters:
Hmem: The handle of the global memory object. This handle is obtained by GlobalAlloc or GlobalRealloc.
return value:
The call succeeded, returning a pointer to the first byte of the object
Call failed, return NULL, can use GetLastError to get error message
Attention:
After you have called GlobalLock to lock a block of memory, be sure to call GlobalUnlock to unlock
GlobalUnlock
Function Description: Unlocking a locked global memory object
Function prototype: BOOL GlobalUnlock (Hglobal hmem);
Parameters: Hmem: Handle to Global Memory object
return value:
Non-0 value, the specified memory object is still in the locked state 0, function execution error, you can use GetLastError to get the error message, if returned no_error, it means that the memory object has been unlocked
Note: This function is actually to reduce the lock counter of the memory object by one, and if the counter is not 0, it means to execute too many GlobalLock
function to lock the memory object, and a corresponding number of GlobalUnlock functions is required to unlock it. If you return an error through the GetLastError function
If the code is error_not_locked, it means it is unlocked or unlocked.
Example:
Malloc memory
hmem = GlobalAlloc (gmem_moveable | Gmem_ddeshare, nsize);
Lock memory
Pmem = (BYTE *) GlobalLock (HMEM);
..................
Unlock memory
GlobalUnlock (HMEM);
GlobalFree (HMEM);
Three summary
Flexible freedom is a major feature of C/s + + language, and this has also been a problem for C + + programmers. When the program becomes more and more complex, memory management will become more complex, a little careless will appear memory problems. Memory leaks are one of the most common memory problems. Memory leaks if not very serious, in a short period of time will not have much impact on the program, which also makes the memory leak problem has a strong concealment, not easy to be found. However no tube
How small the leak is, when the program is running for a long time, its destructive power is amazing, from performance down to memory exhaustion, even affect the normal operation of other programs. Another common feature of the memory problem is that the memory problem itself does not have a very obvious phenomenon, when there is abnormal phenomenon has changed, its site has not occurred when the problem of the scene, which gives debugging memory problems brought great difficulty.
Download the Windows Debug tool, http://www.microsoft.com/whdc/devtools/debugging/default.mspx
After installation, use the Gflags.exe tool in the pageheap to open the
Gflags-p/enable Maind.exe/full
Reuse vs run with debugging, and quickly find the error location, because a typo in a static function causes
This tool is especially useful when writing a stable server program.
Dynamic distribution and example of the second fractional group
One, the general method of dynamically allocating two-dimensional arrays is this: Suppose that the data type that the array is stored in is int
int **p=null;
P=new Int*[nwidth];
if (!p) {return
NULL;
}
for (int j=0;j<nwidth;j++) {
p[j]=new int[nheight];
if (!p[j]) {return
NULL;
}
}
This code is easy to understand, the first allocation of the 1th dimension, in the circular allocation of the 2nd dimension. Assuming that the two-dimensional array is 3x2, each sentence after the completion of the memory situation as shown in the diagram (square represents memory, XX represents random number.) The following is the memory address. Of course, this address is a sign that the facts will not be assigned there. ):
3 Memory units allocated after the first sentence
After circular allocation, note that the following 3 segments of memory are not contiguous. The following table P[n][m] Action array is OK, if the whole block of memory operation will be problematic.
The original intention is to put the following 3 pieces of 6 memory units clear 0, but backfired, the beginning of the 6 memory units from the P 0, p[] can not be used. P only has 3 allocated memory units, but it operates 6, and the other 3 are uncharted regions. Clear the 3 unknown areas behind the dotted line, which is dangerous and may cause the program to crash.
This allocated memory requires a circular release.
There is an improvement on this approach, as follows:
int **p=null;
p=new int *[nwidth];
if (!p) {return
NULL;
}
P[0]=new Int[nwidth*nheight];
if (!p[0]) {
delete[] p;
return NULL;
}
ZeroMemory (p[0],nwidth*nheight*sizeof (int));
for (int i=1;i<nwidth;i++) {
p[i]=p[i-1]+nheight
}
This code solves the problem of discontinuous allocation of space. The memory situation after each sentence is as shown in the figure:
The first sentence is the same as above.
These 6 memory units are allocated at one time, so they are contiguous.
The first address of the data in this two-dimensional array is p[0],p, which is the index first address of the 2nd dimension. So if you want to do a whole memory (buffer buffer) operation on a two-dimensional array, take p[0] as the first address of the object.
To this, the index is associated with the corresponding data address. This two-dimensional array can be manipulated by the following table p[][], and it can manipulate the buffer. Functions that manipulate buffers such as Memcpy,cfile Writehuge and Readhuge are easy to use, eliminating the hassle of 2 cycles.
As for release, there is no need to recycle. Because new 2 times, so just delete2 time on the line:
if (!p) {return
;
}
delete []p[0];
P[0]=null;
Delete[] p;
P=null;
Two examples
<span style= "FONT-SIZE:14PX;"
>//Malloc2d.cpp:Defines The entry point for the console application. #include "stdafx.h" #include <iostream> #include <stdlib.h> #include <string.h> using Namespac
e std;
The first method allocates continuous space void **malloc2d (int row,int col,int size) {void **arr; int indexsize=sizeof (void*) *row;//empty out indexsize size space as?
void* why not?
int totalsize=size*row*col;
Arr= (void**) malloc (indexsize+totalsize); if (arr!=null) {unsigned Char *head;//blog is a void *head version, but compilation is not passed, unsigned char* after the compilation passed, but do not understand why the results of the operation is not head= (UN
Signed char *) arr+indexsize;
memset (arr,0,indexsize+totalsize);
for (int i=0;i<row;i++) Arr[i]=head+size*i*col;
return arr;
} void Free2d (void **arr) {if (arr!=null) free (arr);
}//second method, allocating contiguous space, implementation version of C + +, template <typename t> T **darray_new (int row, int col) {int size=sizeof (t);
void **arr= (void * * *) malloc (sizeof (void *) * row + size * row * col); if (arr!= NULL) {unsigned char * head;
head= (unsigned char *) arr + sizeof (void *) * row;
for (int i=0; i<row; ++i) {arr[i]= head + size * I * COL;
for (int j=0; j<col; ++j) New (head + size * (i * col + j)) t;//This is a more interesting sentence, think about why?
} return (t**) arr; Template <typename t> void Darray_free (T **arr, int row, int col)/Note to one delete, the egg hurts, but for the custom data type, it is necessary {F or (int i=0; i<row; ++i) for (int j=0; j<col; ++j) arr[i][j].~t ();//What the hell is this?! Template destructor? Because you used new?
So with the destructor's delete?
if (arr!= NULL) Free ((void * *) arr);
} int _tmain (int argc, _tchar* argv[]) {//one-dimensional array dynamically allocated//int N;
cin>>n;
An int *p=new int[n];//dynamic allocation method of one-dimensional array//int *p= (int*) malloc (n*sizeof (int));//one-dimensional array dynamic allocation method two//for (int i=0;i<n;i++)
cin>>p[i];
cout<<endl;
for (int i=0;i<n;i++)//cout<<p[i]<< ""; Two-dimensional variable-length array dynamic allocation, I like this method, although the space is not continuous, but also can carry out p[i][j] addressing, why the blog deliberately write aboveThe introduction of the function to achieve has not found too good reason for//int N;
cin>>n;
int *p[2];
P[0]=new Int[n];
P[1]=new int[n+1];
for (int i=0;i<n;i++)//cin>>p[0][i]; cout<<&p[0]<< "" <<&p[1]<<endl;//p[0],p[1] is a continuous//cout<<&p[0]<< " "<<&p[0][0]<<" "<<&p[0][1]<<endl;//p[0]!=p[0][0], but p[0][0],p[0][1] is a continuous version of the////c, divided
With continuous space//int**m= (int**) malloc2d (5,5,sizeof (int));
int i,j;
for (i=0;i<5;i++)//void* generic pointers, to be profiled//for (j=0;j<5;j++)//m[i][j]=0;
for (i=0;i<5;i++)//{//For (j=0;j<5;j++)//cout<<m[i][j]<< "";
cout<<endl;
}//free2d ((void**) m);
int** m=darray_new<int> (5,5)//Notice how the template function is implemented <int>!
int i,j;
for (i=0;i<5;i++) for (j=0;j<5;j++) m[i][j]=1;
for (i=0;i<5;i++) {for (j=0;j<5;j++) cout<<m[i][j]<< ""; cout<<endl;
} darray_free (m,5,5);
return 0; } </span>
Above this article on C + + memory allocation and variable-length array dynamic distribution is a small series to share all the content, hope to give you a reference, but also hope that we support the cloud habitat community.