PRB: Unhandled Exception Using COM Smart Pointers with VC++ (192651)



The information in this article applies to:

  • Collaboration Data Objects (CDO) 1.1
  • Collaboration Data Objects (CDO) 1.2
  • Collaboration Data Objects (CDO) 1.21
  • Microsoft Visual C++, 32-bit Enterprise Edition 5.0
  • Microsoft Visual C++, 32-bit Professional Edition 5.0

This article was previously published under Q192651

SYMPTOMS

Using smart pointers with Visual C++ version 5.0, generated by including a type library with #import, it is possible to experience an unhandled exception error in your application. A common symptom is having near identical code for an object model, such as Collaboration Data Objects (CDO 1.x) that works fine in Visual Basic, but not from C++.

CAUSE

Reference counting is being handled improperly.

RESOLUTION

When reassigning a smart pointer it is important to first set the pointer to NULL. This causes the smart pointers implementation to properly release the previous object before assigning the pointer to the new object. This occurs when you compile and link with Visual C++ 6.0.

MORE INFORMATION

Steps to Reproduce Behavior

This problem can appear in any call in which a Component Object Model (COM) smart pointer is reused. The following example reproduces the problem:
   try {

        _SessionPtr pSession("MAPI.Session");
        pSession->Logon();

        FolderPtr   pFolder = pSession->Inbox;
        MessagesPtr pMessages = pFolder->Messages;
        MessagePtr  pMessage = pMessages->GetFirst();
        _bstr_t body;

        while (pMessage != NULL) {
            body = pMessage->Text;
            _tprintf("%s\n", (LPCTSTR)body);
            pMessage = pMessages->GetNext();
        }

    } catch (_com_error &e) {
        dump_com_error(e);
    }
				
The preceding code fails on the following line because you are now reassigning the smart pointer without first releasing the underlying object:
   pMessage = pMessages->GetNext();
				
For the preceding code to work, that line should be replaced by the following two lines of code:
   pMessage = NULL;
   pMessage = pMessages->GetNext();
				
It is also a good idea to set the pointers to NULL at the end of your code. This must be done if you are going to call the CoUninitialize function in the same scope as the smart pointers.

REFERENCES

Inside COM, Dale Rogerson, Microsoft Press, pg. 218.

Modification Type:MajorLast Reviewed:3/11/2004
Keywords:kbcode kbMsg kbprb KB192651