C ++ practical skills (2)

Source: Internet
Author: User

It's easy to write complicated things. Due to functional requirements, Vczh Library ++ 3.0 is very outrageous to me. To develop and maintain traversal, reduce mistakes caused by carelessness, and enhance unit testing, regression testing, and testing tools, record some development tips for the benefit of others. You are welcome to join us.

The previous article talked about how to check for Memory leakage. In fact, as long as you are willing to use the advanced functions in C ++ STL, memory leakage is easy to avoid. When I develop Vczh Library ++ 3.0, all the test cases are guaranteed to have no memory leakage after running. However, it is a pity that some C ++ teams cannot use exceptions, or even worse, they cannot write constructor destructor or the like. The previous one is okay, and the next one is simply using C. Of course, STL cannot be used in some of these abnormal regulations, so we need a solid foundation to develop C ++ programs.

This article focuses on Pointer issues today. This is because the previous article has been written. Today we will discuss in detail the various situations of memory leaks or wild pointers. Of course, I cannot give all the examples at once, but I can only say something common.

1. overwrite memory with errors.

We mentioned that we should not randomly mess up memset to avoid this problem. In fact, memcpy cannot be used in disorder. Let's look at an example, the simplest:
1 # define MAX_STRING 20;
2
3 struct Student
4 {
5 char name [MAX_STRING];
6 char id [MAX_STRING];
7 int chinese;
8 int math;
9 int english;
10 };
Everyone must be very familiar with this structure. After all, it is a homework question that is frequently written in college ...... Well, you can easily see that this is actually a classic C language. After we get it, we usually initialize it first and then assign values.
1 Student vczh;
2 memset (& vczh, 0, sizeof (vczh ));
3 strcpy (vczh. name, "vczh ");
4 strcpy (vczh. id, "vczhs id ");
5 vczh. chinese = 70;
6 vczh. math = 90;
7 vczh. english = 80;
Why use memset here? Memset is used to set every byte of memory to the same number. The value is 0, so all bytes of the two string members are changed to 0. Therefore, after memset Student, we obtain an empty string when accessing the name and id through the normal method. In addition, if there is a pointer in Student, the 0 pointer indicates that it does not point to any valid object, so reading and writing the object pointed to by the pointer will crash immediately. For other values, 0 is generally used as the initial value, and there is no problem (double or something should be careful ). This is why we use memset when writing a program.

Now that we are making progress in our society, the people are the masters of our lives. We can use C ++ to eliminate the need for hateful C language exploitation! So we use STL to rewrite Student into the following form with a C ++ flavor:
1 struct Student
2 {
3 std: string name;
4 std: string id;
5 int chinese;
6 int math;
7 int english;
8 };
We still need to initialize Student. Otherwise, the three scores are still random values. However, we do not want to assign values to each created instance to initialize city 0. At this time, you may still think about memset. This is wrong! During memset, you will also drop memset for std: string that does not know anything. If the pointer in an empty std: string points to an empty string instead of 0, the internal pointer is flushed to 0, wait for the std: string destructor to delete the pointer, so the memory leakage occurs. Some friends may not know what the above sentence means. Now let's simulate how to implement std: string that cannot be memset.

To prevent memory leakage in memset, the pointer in std: string must always point to a valid object. Of course, we also need to copy the pointer when copying strings. We will not consider various optimization technologies here, but use the simplest method to make a string:
1 class String
2 {
3 private:
4 char * buffer;
5
6 public:
7 String ()
8 {
9 buffer = new char [1];
10 buffer [0] = 0;
11}
12
13 String (const char * s)
14 {
15 buffer = new char [strlen (s) + 1];
16 strcpy (buffer, s );
17}
18
19 String (const String & s)
20 {
21 buffer = new char [strlen (s. buffer) + 1];
22 strcpy (buffer, s. buffer );
23}
24
25 ~ String ()
26 {
27 delete [] buffer;
28}
29
30 String & operator = (const String & s)
31 {
32 delete [] buffer;
33 buffer = new char [strlen (s. buffer) + 1];
34 strcpy (buffer, s. buffer );
35}
36 };
So let's take a look at memset. First, define a string variable, and then drop memset. Let's see what will happen:
1 string s;
2 memset (& s, 0, sizeof (s ));
In the first line, we construct a string s. The string constructor starts to run at this time, so strcmp (s. buffer, "") = 0. In the second line, we dropped the string to memset. In this case, s. buffer = 0. So the function is over, and the string destructor tries to delete the pointer. We know that there is no problem when deleting a 0 value, so there will be no errors in the program. We lost the new char [1] that the constructor assigned to the buffer! Tietong Memory leakage!

Okay. We always have to solve the problem. If we don't use memset, how can we initialize Student? This is very easy to do. We just need to add the constructor to Student:
1 struct Student
2 {
3. // do not repeat those statements
4
5 Student (): chinese (0), math (0), english (0)
6 {
7}
8 };
This makes it much easier. Every time we define a Student variable, all the Members are initialized. Name and id because the string constructor is initialized by itself, all members are also initialized. It's half done to join Student. What should we do if we want to initialize it again? It is also easy:
1 Student vczh;
2. // various usage
3 vczh = Student ();
After an equal sign operator is called, all the members of the old Student will be overwritten by a new initialized Student, just as we will assign a value to an int variable. Of course, because of the frequent occurrence of various replicas, we also need to implement the four functions just like the string example posted above. So far, I have no idea why some teams are not allowed to use constructor. I guess it is unreasonable to use memset.

Ii. Exceptions.

It seems that memory leakage has nothing to do with exceptions, but in fact this situation is more likely to happen. Let's look at an example:
1 char * strA = new char [MAX_PATH];
2 if (GetXXX (strA, MAX_PATH) = ERROR) goto RELEASE_STRA;
3 char * strB = new char [MAX_PATH];
4 if (GetXXX (strB, MAX_PATH) = ERROR) goto RELEASE_STRB;
5
6 DoSomething (strA, strB );
7
8 RELEASE_STRB:
9 delete [] strB;
10 RELEASE_STRA:
11 delete [] strA;
I believe this is a common model. I am not here to Instruct everyone to use goto, but for such examples, using goto is the best solution. But we can see that we use C ++, because there is new here. What if an exception occurs in DoSomething? What if an exception occurs in GetXXX? We don't have any try-catch here. If there is an exception, the function Rick ends, and the two lines of poor delete won't be executed, so the memory leakage occurs!

So how can we avoid Memory leakage in this situation? Some cute friends may think that since there is no catch exception to the memory leak, let's catch it:
1 char * strA = new char [MAX_PATH];
2 try
3 {
4 if (GetXXX (strA, MAX_PATH) = ERROR) goto RELEASE_STRA;
5 char * strB = new char [MAX_PATH];
6 try
7 {
8 if (GetXXX (strB, MAX_PATH) = ERROR) goto RELEASE_STRB;
9 DoSomething (strA, strB );
10}
11 catch ()
12 {
13 delete [] strB;
14 throw;
15}
16}
17 catch ()
18 {
19 delete [] strA;
20 throw;
21}
22
23 RELEASE_STRB:
24 delete [] strB;
25 RELEASE_STRA:
26 delete [] strA;
Can you accept it? Of course not. Where is the problem? Because C ++ does not have try-finally. As you can see, these codes are similar everywhere. Obviously, we need the compiler to help us solve these problems. What is the best solution? It is still the constructor and destructor. In short, remember to use constructor and destructor if you want something to happen in pairs.

Step 1: GetXXX obviously only supports the C mode. Therefore, we need to write a program that supports C ++:
1 bool GetXXX2 (string & s)
& Nbs

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.