C/C ++ returns the internal static member trap

Source: Internet
Author: User

C/C ++ returns the internal static member trap

Chen Hao

Background

When we use C/C ++ for development, there is always a problem that will upset us. This problem is that the code inside and outside the function needs to interact with each other through a memory (for example, the function returns a string). This problem has plagued many developers. If your memory is allocated on the function stack, the memory will be released as the function returns, so, you must return a memory that is still valid outside the function.

This is a problem that has plagued countless people. If you are not careful, you are likely to make mistakes on this. Of course, there are many solutions. If you are familiar with some standard libraries, you can see a variety of solutions. In general, there are the following types:

1) allocate memory on the heap through malloc or new in the function, and then return the memory (because the memory allocated on the heap is globally visible ). This brings about potential memory problems. Because if the returned memory is not released, it is the memory leak. Or is released multiple times, resulting in program crash. These two problems are quite serious, so this design method is not recommended. (In some windows APIs, after you call some APIs, you must also call some of their APIs to release the memory)

2) Let the user input a memory address of his own, and put the memory to be returned in the function into this memory. This is a common method. Many Windows API functions or standard C functions require you to input a buffer and the buffer length. This method should not be uncommon for us. The advantage of this method is that the program outside the function maintains the memory, which is simple and intuitive. But the problem is that it is a little troublesome to use. However, this method minimizes the chance of making mistakes.

3) The third method is quite different. It uses the static feature. Once the static stack memory is allocated, the memory will not be released as the function returns, it is globally visible (as long as you have the address of this memory ). Therefore, some functions use the static feature, that is, they do not need to use the memory on the stack, nor need to input a buffer and its length. As a result, your functions are very beautiful and easy to use.

Here, I want to discuss the third method. The method of using static memory seems good, but it has a trap that you cannot imagine. Let's use an actual case to give an example.

Example

People who have socket programming experience must know a function called inet_ntoa. The main function of this function is to convert a Digital IP address into a string, this function is defined as follows (note its return value ):

Char * inet_ntoa (struct in_addr in );

Obviously, this function will not allocate memory on the heap, but it will not let you pass the buffer of the string into, so he must use the "Return static char []" method. Before continuing our discussion, let's take a look at IP address-related knowledge. The following are the parameters that need to be passed in by the inet_ntoa function: (You may be surprised, what should I do if there is only one member struct in struct? This should be for future scalability of the program)

Struct in_addr {
Unsigned long int s_addr;
}

For IPv4, an IP address consists of four 8-bit bits, which are placed in s_addr. After the high position is reached, This is to facilitate network transmission. If you get an integer value of s_addr: 3776385196. Open your Windows Calculator and see what its binary is? Let's start from right to left, with 8 digits in A group (as shown below ).

11100001 00010111 00010000 10101100

Then, convert each group to a decimal number, and we will get the IP address 172.16.23.225, Which is 225 23 16 172.

Now, let's get down to the truth. We have a program that wants to record the source address and destination address of the network package, so we have the following code:

Struct in_addr SRC, des;
........
........
Fprintf (FP, "source IP address <% S>/T destination IP address <% S>/N", inet_ntoa (SRC), inet_ntoa (DES ));

What will happen? You will find that the source IP address recorded in the file is exactly the same as the destination IP address. What's the problem? So you started to debug your program, and you found that SRC. s_addr and Des. s_addr are fundamentally different (as shown below ). Why is the source and destination of the output file the same? Is it an inet_ntoa bug?

SRC. s_addr = 3776385196; // corresponding to 172.16.23.225
Des. s_addr = 1678184620; // corresponding to 172.16.7.100

The reason is that inet_ntoa () returns the internal static char [] with "self-intelligence", and our program is stepping on this trap. Let's analyze the fprintf code. In fprintf, the compiler calculates inet_ntoa (DES) first, so it returns the address of a string, and then the program calculates the inet_ntoa (SRC) expression and obtains the address of a string. The addresses of these two strings are both static char [] In inet_ntoa (), which is obviously the same address, and when the second request is made for the src ip address, the IP address of the des value must be overwritten by the src ip address. Therefore, the two expressions have the same string memory. At this time, the program will call fprintf to output these two strings (actually one) to the file. Therefore, it is not surprising to get the same result.

Take a closer look at inet_ntoa's man. We can see this sentence: the string is returned in a statically allocated buffer, which subsequent callwill overwrite. confirmed our analysis.

Summary

Let us all ask ourselves, are we using this method in the Process of program writing? This is a dangerous and error-prone method. This trap is hard to prevent. Think about it, if you have such a program:

If (strcmp (inet_ntoa (IP1), inet_ntoa (ip2) = 0 ){
........
}

I wanted to determine whether the two IP addresses are the same, but it was not expected to fall into that trap-to make this conditional expression permanent.

This tells us the following truth:

1) use this method with caution. The static memory inside the return function has a large trap.
2) if this method is required. You must tell everyone who uses this function seriously. Never use this function multiple times in an expression. Besides, it is useless to save the returned memory address or reference instead of copying the memory content returned by the function. Otherwise, you will not be liable for the consequences.
3) C/C ++ is a very dangerous world, if you do not know about it. Go back to Mars.

Note: If you have read efftive C ++, you must know that there is a clause (item 23): do not try to return an object reference. This article also discusses whether to return static variables in the function. The results are also negative.

(Indicate the author and source when reprinting. Do not use it for commercial purposes without permission)

For more articles visit my blog: http://blog.csdn.net/haoel

 

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.