C + + Returns a trap for internal static members

Source: Internet
Author: User

turn from: http://blog.csdn.net/haoel/article/details/1388498

background

There is always a problem in the process of using C + + to bring us trouble. The problem is that the code inside and outside the function needs to interact with a piece of memory (for example, a function returns a string), a problem that bothers many developers. If your memory is allocated on the stack of functions, then the memory will be released with the stack as the function returns, so you must return the memory that is valid outside of the function.

This is a problem that bothers countless people. If you are careless, you are likely to make a mistake on this. Of course there are a lot of solutions, and if you're familiar with some of the standard libraries, you can see a lot of different kinds of solutions. Basically there are the following:

1 Allocate memory within the function through malloc or new on the heap, and then return the block of memory (because the memory allocated on the heap is globally visible). The problem with this is the potential memory problem. Because if the return out of memory is not released, then it is memory leak. Or be repeatedly released, resulting in the crash of the program. Both of these problems are quite serious, so this design method is not recommended. (In some Windows APIs, when you invoke some APIs, you must also call some of his APIs to release the memory)

2 Let the user pass in a piece of his own memory address, and in the function of the memory to be returned to this block of memory. This is a widely used approach at the moment. Many Windows API functions or standard C functions require you to pass in a buffer and the length of the buffer. This approach should be a common occurrence for us. The advantage of this approach is that the function outside of the program to maintain the memory, relatively simple and intuitive. But the problem is that it's a little bit cumbersome to use. But this approach minimizes the chance of making mistakes.

3 The Third Way is more alternative, he took advantage of the static characteristics, static stack memory once allocated, the memory will not be released with the function return, and it is globally visible (as long as you have the address of this block of memory). Therefore, some functions use the static feature, that is, do not use the memory on the heap, nor need the user to pass in a buffer and its length. Therefore, the use of their own functions are very beautiful and easy to use.

Here, I want to discuss some of the third method. Using the static memory method looks good, but it has a trap that you can't imagine. Let's use a case that actually happens to give an example.

Sample

Has the experience of socket programming must know a function is called: Inet_ntoa, this function is the main function of a digital IP address into a string, this function is defined as this (note its return value):

Char *inet_ntoa (struct in_addr in);

Obviously, this function does not allocate memory on the heap, and he does not let you pass the string of buffer entry, then he must use "return static char[]" this method. Before we move on to our discussion, let's take a look at the IP address-related knowledge, and here's the Inet_ntoa parameter that the function needs to pass in: (You might be surprised to see that only one member of the struct is going to do it in struct.) This should be for the future extensibility consideration of the program)

struct IN_ADDR {
unsigned long int s_addr;
}

For IPV4, an IP address is made up of four 8 bit bits, which are placed in the s_addr, high in the rear, for easy network transmission. If you get the integer value of a s_addr is: 3776385196. So, open your Windows calculator and see what its binary is. Let's go from right to left, 8-bit for a group (see below).

11100001 00010111 00010000 10101100

Then turn each group into decimal, so we get: 225 23 16 172, so the IP address is 172.16.23.225.

Okay, here we are. We have a program that wants to record the source and target addresses of the network packets, so we have the following code:

struct in_addr src, des;
........
........
fprintf (FP, "Source IP address <%s> destination IP address <%s>", Inet_ntoa (SRC), Inet_ntoa (DES));

What kind of results will happen. You will find that the source IP address and destination IP address are exactly the same as those recorded in the file. What is the problem? So you start debugging your program and you find that src.s_addr and des.s_addr are fundamentally different (see below). The source and purpose of the output to the file is the same. Is that a inet_ntoa bug.

SRC.S_ADDR = 3776385196; Corresponds to 172.16.23.225
DES.S_ADDR = 1678184620; Corresponds to 172.16.7.100

The reason is that Inet_ntoa () "smart" to the internal static char[] back, and our program is to step on this trap. Let's analyze the fprintf code. When we fprintf, the compiler computes Inet_ntoa (DES), then returns the address of a string, and then the program asks for the Inet_ntoa (SRC) expression and gets the address of a string. These two string addresses are Inet_ntoa () in the static char[], is obviously the same address, and the second time SRC IP, this value of the DES IP address content will be SRC IP coverage. So, the string memory of both expressions is the same, and at this point, the program invokes fprintf to output the two strings (actually one) to the file. So it's not surprising to get the same result.

With a closer look at Inet_ntoa's man, we can see this sentence: The string is returned in a statically allocated buffer, which subsequent calls will OVERWR Ite. confirms our analysis.


Summary

Let us all ask ourselves whether this approach was used in the process of writing a program. This is a more dangerous, error-prone approach. Such traps are impossible to guard against. Think about that if you have this program:

if (strcmp (Inet_ntoa (IP1), Inet_ntoa (IP2)) ==0) {
.... ....
}

I wanted to determine whether two IP addresses are the same, but only to fall into the trap-let this conditional expression forever.

This matter tells us the following several reasons:

1 carefully use this way of design. Returning static memory inside a function is a big trap.
2 If you must use this method. You have to be serious about telling everyone who uses this function, and never use it more than once in an expression. Also, it is not useful to tell them that the contents of the memory returned by the not copy function, but simply to save the returned memory address or reference is useless. Otherwise, the consequences are not responsible.
3 C + + is a dangerous world, if you don't know what he said. Let's go to the temper star.

Attachment: Read effective C + + friends must know that there is a clause (item 23): Do not attempt to return an object's reference. This article also discusses whether to return static variables within a function. The result is also negative.

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.