Thread: AddRef and Release

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    1,579

    AddRef and Release

    Hello everyone,


    Here is section of code I wrote about AddRef and Release. My questions are,

    1. Are they correct code?
    2. It looks redundant to call so many times of AddRef and Release just to make the counter consistent, if you were me, do you have ways to write better code?

    Code:
    IX* pI = NULL;
    pI = pI1;
    pI -> AddRef();
    
    ...
    
    pI -> Release(); // release before binding to a new interface
    pI = pI2;
    pI -> AddRef();
    
    ...
    
    pI -> Release(); // release before binding to a new interface
    pI = pI3;
    pI -> AddRef();
    
    ...

    thanks in advance,
    George

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    AddRef() adds one to the reference count and Release() decrements it by one.
    When the reference count reaches 0, the object is destroyed. So you shouldn't call Release() before reassigning. Call it after.
    Even better it to wrap the COM object in a RAII class where the constructor calls AddRef and the destructor calls Release().
    Last edited by Elysia; 02-03-2008 at 09:05 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Thanks Elysia,


    I do not agree with "So you shouldn't call Release() before reassigning". I think you mean write code like this,

    Code:
    pI = pI2;
    pI -> Release();
    pI -> AddRef();
    other than like

    Code:
    pI -> Release(); // release before binding to a new interface
    pI = pI2;
    pI -> AddRef();
    Ths problem of your comment is pI1 may pointed to another component, and we need to call "its (the component pointed by pI1)" Release, other than pI2's Release.

    Please feel free to correct me if I am wrong.

    Quote Originally Posted by Elysia View Post
    AddRef() adds one to the reference count and Release() decrements it by one.
    When the reference count reaches 0, the object is destroyed. So you shouldn't call Release() before reassigning. Call it after.
    Even better it to wrap the COM object in a RAII class where the constructor calls AddRef and the destructor calls Release().

    regards,
    George

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by George2 View Post
    Thanks Elysia,

    I do not agree with "So you shouldn't call Release() before reassigning". I think you mean write code like this,

    other than like

    Ths problem of your comment is pI1 may pointed to another component, and we need to call "its (the component pointed by pI1)" Release, other than pI2's Release.

    Please feel free to correct me if I am wrong.

    regards,
    George
    But if you create a COM object -> ref count = 1.
    You call Release before reassigning and calling AddRef -> ref count = 1 - 1 = 0. Boom! Object destroyed!
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Thanks Elysia,


    The object will not be destroyed if any other interface holds the reference to it, like pI1. But your implementation also has issue as I pointed in post #3. Any comments?

    Quote Originally Posted by Elysia View Post
    But if you create a COM object -> ref count = 1.
    You call Release before reassigning and calling AddRef -> ref count = 1 - 1 = 0. Boom! Object destroyed!

    regards,
    George

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    How does the object know that something holds a reference to it?
    Everytime you create an object, its reference count is increased. So when you no longer need the interface, you decrement it through Release and get rid of the pointer. That way the object is destroyed.
    You're destroying it prematurely.

    For all intents and purposes, if you make another pointer to the object, call AddRef first, then call Release on the old pointer and get rid of it.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Sorry Elysia, I do not agree with you. :-)


    1. "You're destroying it prematurely." Do you mean destroyed at statement "pI -> Release()"?

    No. Please look at my original code. Suppose pI1 holds reference to the object instance, and even if we invoked pI -> AddRef(), then I -> Release(), pI1 still holds the reference to the object instance, so it is not destroyed at the statement pI -> Release().

    Code:
    IX* pI = NULL;
    pI = pI1;
    pI -> AddRef();
    
    ...
    
    pI -> Release(); // release before binding to a new interface
    pI = pI2;
    pI -> AddRef();
    
    ...
    
    pI -> Release(); // release before binding to a new interface
    pI = pI3;
    pI -> AddRef();
    
    ...
    2. "call Release on the old pointer and get rid of it"

    No. If we still need the old pointer, we should not call Release on it. Suppose we have an overlapped life time of interface? Agree?

    If I am wrong with either (1) or (2), plesae feel free to correct me. :-)

    Quote Originally Posted by Elysia View Post
    How does the object know that something holds a reference to it?
    Everytime you create an object, its reference count is increased. So when you no longer need the interface, you decrement it through Release and get rid of the pointer. That way the object is destroyed.
    You're destroying it prematurely.

    For all intents and purposes, if you make another pointer to the object, call AddRef first, then call Release on the old pointer and get rid of it.

    regards,
    George

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by George2 View Post
    1. "You're destroying it prematurely." Do you mean destroyed at statement "pI -> Release()"?

    No. Please look at my original code. Suppose pI1 holds reference to the object instance, and even if we invoked pI -> AddRef(), then I -> Release(), pI1 still holds the reference to the object instance, so it is not destroyed at the statement pI -> Release().
    How does the object know you hold a reference to it? It doesn't! It can't. It doesn't work that way. If there was a way to tell whenever a pointer held a reference to an object, there would be no need for reference counting, would there?

    2. "call Release on the old pointer and get rid of it"

    No. If we still need the old pointer, we should not call Release on it. Suppose we have an overlapped life time of interface? Agree?
    Absolutely. Only call Release() if you don't need the pointer anymore.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    You shouldn't really ever need to call AddRef or Release directly. Just use a CComPtr<T> to hold the pointer to an interface of type T, instead.

    I just fixed a nasty refcount bug a few hours ago in fact. Don't let this kind of bug occur in the first place.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  10. #10
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Hi Elysia,


    Quote Originally Posted by Elysia View Post
    How does the object know you hold a reference to it? It doesn't! It can't. It doesn't work that way. If there was a way to tell whenever a pointer held a reference to an object, there would be no need for reference counting, would there?
    Sure, it could. It is what AddRef and Release in COM doing. In the implementation of AddRef, for example, we may invoke InterLockedIncrement to increase the counter member of the class instance to maintain the reference count. So, in this way, the object instance could know how much references are binded to it.

    Have I understood your point correct? Please feel free to correct me if I am wrong.

    Thanks for your advice, iMalc!


    Do you have any comments to my code, do you think it is correct from function point of view even if it looks redundant?

    Quote Originally Posted by iMalc View Post
    You shouldn't really ever need to call AddRef or Release directly. Just use a CComPtr<T> to hold the pointer to an interface of type T, instead.

    I just fixed a nasty refcount bug a few hours ago in fact. Don't let this kind of bug occur in the first place.

    regards,
    George
    Last edited by George2; 02-03-2008 at 11:49 PM.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by George2 View Post
    Sure, it could. It is what AddRef and Release in COM doing. In the implementation of AddRef, for example, we may invoke InterLockedIncrement to increase the counter member of the class instance to maintain the reference count. So, in this way, the object instance could know how much references are binded to it.
    No. Note that knowing how many pointers are bound to an instance and reference counting aren't the same thing.
    You are responsible for maintaining the correct reference count so that the number of pointers pointing to the same object is the same as the reference count. You can have one pointer to the object, yet the reference count can be 10. If you toss away that pointer, you have a memory leak because the reference count will still be 9 if you called Release.
    Similarly, you can have a thousand pointers pointing to the object yet the reference count is only 1. So if you call Release, all those pointers will be invalid because reference count reaches 0 and the object is destroyed.

    You must understand that it is the reference count that controls whether an object lives or dies. And just creating another pointer to the same object does not magically increase the reference count.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Thanks Elysia,


    I have understood your point. Seems you have a different definition of reference count and pointer count. According to COM reference count practices, mentioned in the book Inside COM, if you assign the value to one pointer to interface, you need to call AddRef.

    Looks like in COM world, they maintain pointer count as reference count, right? Looks like the pure reference count is not easy to maintain, suppose you have mixed use of local and global variables.

    Quote Originally Posted by Elysia View Post
    No. Note that knowing how many pointers are bound to an instance and reference counting aren't the same thing.
    You are responsible for maintaining the correct reference count so that the number of pointers pointing to the same object is the same as the reference count. You can have one pointer to the object, yet the reference count can be 10. If you toss away that pointer, you have a memory leak because the reference count will still be 9 if you called Release.
    Similarly, you can have a thousand pointers pointing to the object yet the reference count is only 1. So if you call Release, all those pointers will be invalid because reference count reaches 0 and the object is destroyed.

    You must understand that it is the reference count that controls whether an object lives or dies. And just creating another pointer to the same object does not magically increase the reference count.

    regards,
    George

  13. #13
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Sorry, Elysia, in this case you're just totally wrong.

    George2 is right.

    iMalc is more right.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  14. #14
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Thanks CornedBee,


    Quote Originally Posted by CornedBee View Post
    Sorry, Elysia, in this case you're just totally wrong.

    George2 is right.

    iMalc is more right.
    My question is answered.


    regards,
    George

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by CornedBee View Post
    Sorry, Elysia, in this case you're just totally wrong.
    Well then, could you actually elaborate a bit?
    Does objects exist while there is a pointer to them or do they go away when the reference count is 0?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How to monitor process creation?
    By markiz in forum Windows Programming
    Replies: 31
    Last Post: 03-17-2008, 02:39 PM
  2. Ban pointers or references on classes?
    By Elysia in forum C++ Programming
    Replies: 89
    Last Post: 10-30-2007, 03:20 AM
  3. AddRef and Release function of COM inteface
    By George2 in forum C++ Programming
    Replies: 0
    Last Post: 10-18-2007, 06:35 AM