Effective use and design of the COM smart pointer-clause 12: Use attach () and detach () to adjust the reference count if necessary

Source: Internet
Author: User
Clause 12: Use attach () and detach () to adjust reference count if necessary. For more information, see http://blog.csdn.net/liuchang5.

Suppose we use a third-party function, or it is also written by us, but it is only because we didn't use smart pointers at first. So its implementation may look like this:

Iview * getview (INT nindex) {iview * pview = m_views [nindex]; pview-> addref (); // The reference count is increased once. Return pview ;}

This function is easy to understand. When the parameter is passed out, the addref () is called by following the three rules of reference count (). But what if we use it like this?

Void useview (INT nindex) {ccomptr <iview> spview = NULL; spview = getview (0); // the root cause of the error is spview-> userit ();}

This once again shows the worst result of the reference counting problem-resource leakage without sound.

If you have not found any of the above reference counting errors, let's take a single step to see how this resource leakage problem occurs:

1. First, a smart pointer is created in useview. It points to NULL;

2. Call getview (0) to return an interface pointer and increase the reference count of the component.

3. getview (0) assigns an interface pointer to a smart pointer through the value assignment operator that is overloaded with smart pointers. In this case, the value assignment operator adds a reference technology.

4. Use the smart pointer interface.

5. smart pointer to the stack. The reference count is decreased once.

After carefully checking the above process, you will find that the number of cited technologies has increased twice, but it has only decreased once. Therefore, the root cause of the error is that the value assignment operator of the smart pointer overload adds one more reference count. Some people think of the following method to solve this problem:

Void useview (INT nindex) {ccomptr <iview> spview = NULL; spview = getview (0); // the root cause of the error is spview-> release (); // solve this problem? It's hard to understand. Spview-> userit ();}

If you see such code, you may ask. Where is the reason for the release () operation? Why is there a single release () when there is no addref (). However, if you are aware of this process, you will find that the reason for doing so is only to offset one side effect of the value assignment operator (adding the reference count ). However, this makes it difficult for people to understand and support some resource allocation interfaces, which may cause some performance loss.

The correct solution is as follows:

Void useview (INT nindex) {ccomptr <iview> spview = NULL; spview. Attach (getview (0); // OK, the problem is solved. It is easy to understand its meaning. Spview-> userit ();}

The attach operation provided by the smart pointer can bind the interface pointer to the smart pointer without increasing its reference count. Let's take a look at the function running process. Is there a balance between the increase and decrease of the reference count?

You may say that the above getview interface is not very in line with the com design habits, because it does not use hresult as the return value to identify whether the call is successful or not. In your new version, you use hresutl as the return value and an interface pointer as the output parameter. Most importantly, you think of using smart pointers to implement this function. These ideas are reasonable, so they look like the following:

Hresult HR getview (INT nindex, iview ** ppview) {ccomptr <iview> spview = m_views [nindex]; If (failed (spview-> isvisable () return e_faild; * ppview = spview; // ou ~ Return s_ OK ;}

This is another potentially confusing mistake. If you cannot find him, we can only "One step" at a time. This may trigger your brains, but it is more worthwhile than program collapse or memory leakage:

1. First, a smart pointer is created in useview. It points to a COM interface, and the interface reference count increases.

2. Call isvisable () and determine whether it is successful. If the pointer fails, the smart pointer is parsed. The reference count is decreasing. If yes, proceed to the next step.

3. assign a smart pointer to an interface pointer, and an implicit conversion is completed. The reference count remains unchanged.

4. The function ends. The smart pointer is destructed. The reference count is decreasing.

The preceding steps show that if the function fails to be executed, there is no problem. The increase or decrease of the reference count is balanced. But what if this function is successful? You may have to go back to Clause 1 to see the troublesome reference counting rules:

"Addref is called before return. For the functions that return the interface pointer, apply the corresponding pointer to call addref before the return. These functions include QueryInterface and createinstance. In this way, when a customer obtains an interface from this function, he does not need to call addref ."

Obviously, this is not the case here. The consequence is that a pointer or reference may receive this interface pointer, but the reference count is not increased!

You may have thought of a way to manually adjust the count before it leaves the stack. Do not do this, it will make the semantics unclear. The best solution is to use the detach operation:

Hresult HR getview (INT nindex, iview ** ppview) {ccomptr <iview> spview = m_views [nindex]; If (failed (spview-> isvisable () return e_faild; * ppview = spview. detach (); // before the smart pointer goes out of the stack, it is separated from the interface pointer. Return s_ OK ;}

This is perhaps the most worrying part of smart pointers. It only automates reference counting to a certain extent. But it does not completely solve this problem. The root cause of the problem is that smart pointers want to automate reference counting and must be compatible with the three rules left behind by the COM reference technology. Programmers may have to be careful about these potential problems.

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.