Common C-language memory errors and Countermeasures

Source: Internet
Author: User
Tags terminates

http://see.xidian.edu.cn/cpp/html/483.html

One, the pointer does not point to a piece of legitimate memory

A pointer variable is defined, but no memory is allocated to the pointer, that is, the pointer does not point to a piece of legitimate memory. Simple examples are not, here are some of the more covert examples.

1. Struct member pointer not initialized
struct student
{
Char *name;
int score;
}stu,*pstu;
Intmain ()
{
strcpy (Stu.name, "Jimy");
Stu.score = 99;
return 0;
}
Many beginners make this mistake and don't know what's going on. The struct variable stu is defined here, but he did not think of the struct's internal char *name, when the member defined the struct variable stu, only assigned 4 bytes to name, the pointer variable itself. The name pointer does not point to a valid address, when it is only stored in some garbled characters. So when the strcpy function is called, the string "Jimy" is copied to the memory referred to as garbled, and the memory name pointer does not have access at all, causing an error. The workaround is to have a space for the name pointer malloc.

Similarly, some people make the following error:
Intmain ()
{
Pstu = (struct student*) malloc (sizeof (struct student));
strcpy (Pstu->name, "Jimy");
Pstu->score = 99;
Free (PSTU);
return 0;
}
The pointer variable pstu is allocated memory, but the name pointer is also not allocated memory. Error as in the first case above, the solution is the same. Here, a malloc gives the illusion that the name pointer is also allocated memory.

2. There is not enough memory allocated for the struct pointer
Intmain ()
{
Pstu = (struct student*) malloc (sizeof (struct student*));
strcpy (Pstu->name, "Jimy");
Pstu->score = 99;
Free (PSTU);
return 0;
}
When allocating memory for Pstu, the allocated memory size is inappropriate. Here, sizeof (struct student) is mistakenly written as sizeof (struct student*). Of course, the name pointer is also not allocated memory. The solution is ibid.

3, the function of the entry check
Whenever we use pointers, make sure the pointers are valid.

The parameter is generally checked by using assert (NULL! = p) At the entrance of the function. Use if (NULL! = p) to validate in a non-parametric place. But there is a requirement that p be initialized to null at the same time as the definition. As the above example, using the IF (NULL! = p) Checksum does not work because the name pointer is not initialized to NULL, and its interior is a non-null garbled.

Assert is a macro, not a function, that is included in the Assert.h header file. If the value in parentheses behind it is false, the program terminates and prompts for an error, and if the value in the parentheses below is true, the subsequent code continues to run. This macro only works on the debug version, and the release version is fully optimized by the compiler, which does not affect the performance of the code.

Some people may ask, since the release version is completely optimized by the compiler, the release version is not exactly this parameter entry check it? So that's the same thing as not using it?

Yes, there is no such check in the release version where the Assert macro is used. But we need to know that the Assert macro is just for the purpose of debugging the code, and it's all about getting rid of the error as much as possible while debugging the function, rather than waiting for the release. It has no function of debugging itself. Another point is that the parameter error is not a problem with this function, but the caller passed the argument has a problem. The Assert macro can help us locate the error instead of excluding it.

Second, the memory allocated for the pointer is too small

The pointer is allocated memory, but the memory size is insufficient, resulting in an out-of-bounds error.
Char *p1 = "ABCDEFG";
Char *P2 = (char *) malloc (sizeof (char) *strlen (p1));
strcpy (P2,P1);
P1 is a string constant with a length of 7 characters, but with a memory size of 8 byte. Beginners often forget the end of the string constant flag "\". This will cause the last empty character "P1" in the string to be copied to P2. The workaround is to add this string end marker:
Char *P2 = (char *) malloc (sizeof (char) *strlen (p1) +1*sizeof (char));
It is important to note that only string constants have an end marker. For example, the following notation does not have an end marker:
Char a[7] = {' A ', ' B ', ' C ', ' d ', ' e ', ' f ', ' G '};
Also, do not omit the sizof (char) notation because the char type is 1 bytes in size. This will only reduce your code portability.

Three, the memory allocation is successful, but not initialized

This error is often caused by the notion that there is no initialization or that the value is naturally 0 after the memory is allocated well. The uninitialized pointer variable may not seem so serious, but it is really a very serious problem, and it is often difficult to find the cause of this error.

There was a student who was writing a Windows program and wanted to call a font of the fonts. Calling this font requires populating a struct. He naturally defines a struct variable and assigns the font code he wants to the relevant variable. However, the problem is, no matter how to debug, he needs the font effect is always not out. After I checked his code, I didn't find any problems, so I was stepping through the debugging. When observing the memory of this struct variable, it is found that several members have a garbled value. is one of the characters of a bad curse! Because the system will search for matching fonts in the font based on the values of certain members in the struct, this font is called when the values match some of the fonts in the font. But unfortunately, it is because of these few garbled, resulting in no match to find the font! Because the system can not distinguish what data is garbled, what data is valid data. As long as there is data, the system takes it for granted that it is valid.

Perhaps this serious problem is rare, but it must not be taken lightly. So when defining a variable, the first thing to do is initialize. You can initialize it to a valid value, such as:
int i = 10;
Char *p = (char *) malloc (sizeof (char));
But often this time we are not sure of the initial value of this variable, so that it can be initialized to 0 or null.
int i = 0;
char *p = NULL;
If you define an array, you can initialize it like this:
int a[10] = {0};
or use the Memset function to initialize to 0:
memset (A,0,sizeof (a));
The Memset function has three parameters, the first is the memory start address to be set, the second parameter is the value to be set, and the third parameter is the memory size to be set, in bytes. We don't want to discuss the usage of memset function too much, if you want to know more, please refer to the relevant information.

If the pointer variable is not initialized, it causes the IF statement or assert macro to fail. This, which has been analyzed above.

Iv. memory out of bounds

The memory allocation succeeds and has been initialized, but the operation crosses the memory boundary. This error is often caused by "1" or "less 1" when manipulating arrays or pointers. Like what:
int a[10] = {0};
for (i=0; i<=10; i++)
{
A[i] = i;
}
Therefore, the loop variable for the For loop must use the half-open half-closed interval, and if it is not a special case, the loop variable should start at 0 as far as possible.

V. Memory leaks

Memory leaks are almost impossible to avoid, both veteran and novice, and this problem exists. Even software, including Windows,linux, is more or less a memory leak. Perhaps for the general application software, this problem seems to be not so prominent, restart it will not cause too much loss. But what if you are developing embedded system software? such as car braking systems, pacemakers and other high security requirements of the system. You can not let the pacemaker restart it, the Lord Hades is very hospitable.

The memory that is leaking is the memory on the heap (which does not discuss leaks such as resources or handles), that is, the memory allocated by the MALLOC series function or the new operator. If no time free or delete is used, the memory cannot be freed until the entire program terminates.

1, hometown to seek fertile land
How to understand this memory allocation and release process? Let's look at the following dialogue:
Viva ye: Eiching, you have made a contribution for me, what do you want to reward?
A hero: Long live, gold and silver, minister as dirt. The elder is old, wants to hometown. The minister begging fertile land thousand acres to shade hereafter, do not have him to beg.
Viva ye: Eiching, you toiled, but only to such a small reward, I am today as you wish. Hu Liu Vice minister, see whether there are still thousands of acres of huguang area of fine farmland has never worrier.
Liu Vice minister: Changsha still has more than 50,000 acres of fine farmland has not worrier.
Viva Ye: In Changsha, the fertile farmland thousand acres worrier Eiching. Eiching, fertile land thousand acres, you want to use AH?
A hero: Long live Xie. Changsha area, suitable for planting rice, the minister wanted to grow rice. Rice needs to be divided into an acre of farmland, easy to farm.
。。。。

2. How to use the malloc function
Do not be confused, in fact, this small dialogue above, is the use of malloc process. Malloc is a function that is dedicated to allocating memory from the heap. There are several requirements to use the malloc function:
Who is the memory allocated to? Here is the allocation of fertile land to a hero.
How much memory is allocated? Here is the allocation of 1000 acres.
Are there enough memory allocations? There is still enough fertile land to distribute.
What format of data will the memory be used to store, i.e. what is memory used for?
Here is used to grow rice, need to divide the field into an acre. Where is the allocated memory? This is in Changsha.

If these five points are OK, then the memory can be allocated. The following is a first look at the prototype of the malloc function:
(void *) malloc (int size)
The return value of the malloc function is a pointer of type void, and the parameter is of type int, which is the amount of memory requested for allocation, in bytes. After the memory allocation succeeds, the malloc function returns the first address of the memory. You need a pointer to receive this address. However, because the return value of a function is of type void *, it must be cast to the type you receive. That is, this memory will be used to store what type of data. Like what:
Char *p = (char *) malloc (100);
Allocate 100 bytes of memory on the heap, return the first address of the memory, cast the address to char * Type and assign the pointer variable p to char * type. It also tells us that this memory will be used to store data of type char. This means that you can only manipulate this memory with the pointer variable p. The memory itself does not have a name, and access to it is anonymous.

Above is the process of successfully allocating a chunk of memory using the malloc function. But can you assign success every time?

Not necessarily. Above the dialogue, the emperor let the Hu Vice Minister query whether there is enough fertile land has not been allocated. It is also important to note that using the malloc function: if the requested memory block is larger than the remaining block of memory on the heap (the entire block), the memory allocation fails and the function returns NULL. Note that the "Heap of memory remaining" is not the sum of all the remaining blocks of memory, because the malloc function is requesting contiguous chunks of memory.

Since the malloc function has failed to request memory, we must use the IF (NULL!) when using pointers to this memory. = p) Statement to verify that the memory is indeed allocated successfully.

3. Request 0 bytes of memory with the malloc function
Another question: does requesting 0-byte memory with the malloc function return a null pointer?

You can test it, or you can find the documentation for the malloc function. To request 0 bytes of memory, the function does not return NULL, but instead returns a normal memory address. But you can't use this 0-size memory. A tick on this good ruler, the scale itself is not of length, only a certain two scale together to measure the length. Be careful with this because if (NULL!) = p) Statement validation will not work.

4. Memory Release
Since there is a distribution, it must be released. Otherwise, the limited memory will always run out, while the memory that is not freed is idle. What corresponds to malloc is the free function. The free function has only one parameter, which is the first address of the block of memory to be freed. For example, the above example:
Free (p);
The free function looks pretty tough, but what exactly does it do? In fact, it does one thing: the relationship between the cut-off pointer variable and this block of memory. For example above, we can say that the malloc function allocates memory blocks that belong to P, because our access to this memory needs to be done through P. The free function is to sever all relationships between this memory and P. There is no more involvement between p and that piece of memory. As for the pointer variable p itself holds the address unchanged, but it has no ownership of the memory at this address. The stored value of the freed memory has not changed, but it is no longer available.

This is the function of the free function. According to the above analysis, if you use the free function for p more than two consecutive times, an error will definitely occur. Because the first use of the free function, p belongs to the memory has been released, the second time the use of no memory can be freed. In this regard, I was in class to let the students remember: must be monogamous, or it must be wrong.

malloc two times only free memory leaks; If malloc is free two times, it will definitely go wrong. In other words, the number of malloc used in the program must be equal to free, or there must be an error. This error mainly occurs when the malloc function is recycled, and the malloc and free times are often mistaken. Here's an exercise:
Write two functions, one to generate the linked list, and one to release the linked list. Only one header pointer is used for parameters of two functions.

5. After memory release
Since the address saved by the pointer variable p itself after using the free function does not change, then we need to re-convert the value of p to null:
p = NULL;
This null is the "chain of wild dogs" we said before. If you don't tie it up, it'll be a problem sooner or later. Like what:
After free (p), you use if (NULL!). = p) can such a check statement still work? For example:
Char *p = (char *) malloc (100);
strcpy (P, "hello");
Free (p); /* p refers to the memory being freed, but the address referred to by P is still the same */
...
if (NULL! = p)
{
/* Does not play an anti-error function */
strcpy (P, "World"); /* ERROR */
}
After releasing the block memory, the pointer is not NULL, and the pointer becomes the "wild Pointer", and the book is called "Dangling pointer". It's dangerous, and it's a place that's often wrong. So be sure to remember one: after free, be sure to place null on the pointer.

At the same time, leave a question: is the null pointer consecutive free multiple errors? If you were to design the free function, what would you do with the problem?

Six, the memory has been released, but continue to use the pointer to the

There are generally three kinds of situations here:
The first is that, as stated above, free (p) continues to access memory through the P pointer. The solution is to place P null.
The second type: The function returns the stack memory. This is the most easily made mistake for beginners. For example, an array is defined inside the function, and a return statement is used to return a pointer to the array. The solution is to figure out the life cycle of the variables on the stack.
The third type: memory usage is too complex to figure out which block of memory is being released and which is not. The workaround is to redesign the program to improve the invocation relationship between objects.

The above discussed in detail the common six kinds of errors and solutions, I hope readers read carefully, try to make their own for each error occurred in the cause and prevention means to learn from the chest. Be sure to practice more, debug more code, and experience more.

Common C language Memory errors and Countermeasures (RPM)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.