?
Solved

Intermitent crash on CoUninitialize();

Posted on 2002-07-17
14
Medium Priority
?
1,150 Views
Last Modified: 2012-05-04
Hi everybody,

I use a COM object that export one method. Since I want to use it in few places in the program, I've made a wrapper in order to do the "com initialisation stuff" in only one file.

Here's what I do : In a .cpp file I create a static object. In its constructor, I initialize COM and create an instance of this object. In the destructor, I release the object and uninitialize COM. Since that object is static, its ctor is called at the beginning of the program and its dtor is called at the end of the prog.
The ctor and dtor are called from the main thread.

A crash happend -rarely- on the CoInitialize()...

Here are some extra info to help you look the good direction :
- Windows NT sp6a.
- VC++ 6.0.
- The problem happen even if the COM object is not registred, so not created and "myExportedFunction" is never called.
- The main thread is CoInitialized with : CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
- No other COM objects are created in the main thread (or in that app).
- The code resides in a .lib that is staticly link with the main exe.
- Here is the stack of the crash :
073c8d20()
USER32! 77e71303()
USER32! 77e71962()
NTDLL! 77f763ef()
USER32! 77e755a8()
OLE32! 77b44e21()
OLE32! 77b45185()
MyWrapperObj::~MyWrapperObj() line 123 <-= The CoUninitialize() line.
$E24() + 13 bytes
doexit(int 0, int 0, int 0) line 353
exit(int 0) line 279 + 13 bytes
WinMainCRTStartup() line 345
KERNEL32! 77f1b9ea()

Here's the .cpp code :

#include "MyCOMWrapper.h"
#include "atlbase.h"
#import  "ACOMObject.dll" named_guids no_namespace

class MyWrapperObj{
  public:
    bool mIsReady;  
    IACOMObject*  mpACOMObject;

  public:
    MyWrapperObj(void)
    {
      HRESULT hr;
      mpACOMObject = NULL;
   
      hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

      if ( SUCCEEDED(hr) )
      {
        hr = CoCreateInstance(CLSID_ACOMObject, NULL,
             CLSCTX_ALL, IID_ACOMObject,
            (void**)&mpACOMObject );
        mIsReady   = SUCCEEDED(hr);
      }
    }

    ~MyWrapperObj(void)
    {
      mIsReady = false;
      if (mpACOMObject != NULL)
      {
        mpACOMObject->Release();
      }
      CoUninitialize();
    }    
};

static MyWrapperObj theObject;

void myExportedFunction()
{
  if (mIsReady)
  {
    theObject.mpACOMObject->doStuff();
  }
}


Et voilà ! I think I included all important information. I ask your help because my solution bag is now empty and I hope yours contains the answer I need.

Thanks ans good luck,

renam00


0
Comment
Question by:renam00
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 3
  • +1
14 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 7159949
Install the NT4 SP6a Debug Symbols first (http://www.microsoft.com/ntserver/nts/downloads/recommended/SP6/debug/default.asp) - this will make an analysis much easier, as we could see the actual function names instead of

073c8d20()
USER32! 77e71303()
USER32! 77e71962()
NTDLL! 77f763ef()
USER32! 77e755a8()
OLE32! 77b44e21()
OLE32! 77b45185()
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7160192
I believe that C++ does not guarantee any order of execution of static constructors and destructors.  You could try being more explicit about creating and destroying the object.

What if your static object just did the CoInitialize and CoUnititialize, and you used CreateCreateInstance only when you need the object?

-- Dan
0
 
LVL 22

Expert Comment

by:ambience
ID: 7161338
I believe that you must call CoUninitialize before process termination begins i.e. before WinMain/main returns.

try something like

MyWrapperObj* p_theObject = 0;

void main()
{
    MyWrapperObj theObject;
    p_theObject = &theObject;

}

see if there are any more errors ?
correct me if wrong
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 22

Expert Comment

by:ambience
ID: 7161341
oops, i didnt realize it resides in a lib file. Are yuo using CoInit and CoUninit in your main file too ?
0
 

Author Comment

by:renam00
ID: 7162259
Hi everybody and thanks to you all.

jkr :
-----
Installing the symbols was agood idea. I did it but when a crash happen the stack was very different :
077c8d20()
USER32! DispatchClientMessage@20 + 42 bytes
USER32! __fnDWORD@4 + 36 bytes
NTDLL! KiUserCallbackDispatcher@12 + 19 bytes
USER32! DispatchClientMessage@20 address 0x77e712d9
SXLRT233D! 1000c72e()

Is there a different version of the symbols depending of the server or workstation nature of windows ? From the ms web site, I say no.

DanRollins
----------
Create and destroy the object at every call is not an option since it would be too time consuming and because I want to understand the cause of the problem.
Also, even if the creation\destruction order is not garantee, I know that the ctor is called only once at the beginning of the program and the the dtor is called only once at the end. And sometimes it crashes.

Ambiance
--------
I call CoInitialize/CoUnInitialize on every thread that may use COM object. But keep in mind that in my load test, the component "ACOMObject.dll" is not registred and no COM call is made. It's just a "startup & shutdown" scenario.
But one remark get my attention, you say that I must call CoUninitialize before process termination begins. Can you be more precise about this information. Maybe give me some reference. Since in the (original) stack  I have the two following calls :
doexit(int 0, int 0, int 0) line 353
exit(int 0) line 279 + 13 bytes
I let me think that the process terminaison begins, what do you think ?


So thank again everybody and I'm open to any clue, tracks or ritual sacrifice you may suggest !

renam00
0
 
LVL 86

Expert Comment

by:jkr
ID: 7162270
>>Is there a different version of the symbols depending of
>>the server or workstation nature of windows

No, not at all. Do you have the "High-Encryprion Pack" installed (or not)? You will have to pick the correspoding symbols...
0
 

Author Comment

by:renam00
ID: 7162275
Hi everybody and thanks to you all.

jkr :
-----
Installing the symbols was agood idea. I did it but when a crash happen the stack was very different :
077c8d20()
USER32! DispatchClientMessage@20 + 42 bytes
USER32! __fnDWORD@4 + 36 bytes
NTDLL! KiUserCallbackDispatcher@12 + 19 bytes
USER32! DispatchClientMessage@20 address 0x77e712d9
SXLRT233D! 1000c72e()

Is there a different version of the symbols depending of the server or workstation nature of windows ? From the ms web site, I say no.

DanRollins
----------
Create and destroy the object at every call is not an option since it would be too time consuming and because I want to understand the cause of the problem.
Also, even if the creation\destruction order is not garantee, I know that the ctor is called only once at the beginning of the program and the the dtor is called only once at the end. And sometimes it crashes.

Ambiance
--------
I call CoInitialize/CoUnInitialize on every thread that may use COM object. But keep in mind that in my load test, the component "ACOMObject.dll" is not registred and no COM call is made. It's just a "startup & shutdown" scenario.
But one remark get my attention, you say that I must call CoUninitialize before process termination begins. Can you be more precise about this information. Maybe give me some reference. Since in the (original) stack  I have the two following calls :
doexit(int 0, int 0, int 0) line 353
exit(int 0) line 279 + 13 bytes
I let me think that the process terminaison begins, what do you think ?


So thank again everybody and I'm open to any clue, tracks or ritual sacrifice you may suggest !

renam00
0
 

Author Comment

by:renam00
ID: 7162285
I installed the high-encryption pack symbols since the aboutbox of ms explorer say "cypher strength 128 bits". I had this stack few times, always the same, always on shutdown and alwaws on the main thread. I don't understand because I used symbols on othe version of windows and it worked well. Also, I get the sp6a info from the "winver" command, so It should be true.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7163025
It could be a little bit like a problem I had with ODBC.  After I deleted my CDatabase object, I would get a callback into it from the ODBC manager.  Ihis sat squarely in the realm of the metaphysical, kind of like Houdini from the grave or maybe ET phoning home (my metaphor engine is on the blink again).

>.and I'm open to any clue, tracks or ritual sacrifice you may suggest !
In the API documentation for DllMain, there is some interesting warnings about what should not take place directly upon startup and shutdown.  I don't know if it applies, but it's awful scary so I always do most construction and teardowns elsewhere in the program (I provide some sort of Open and Close fn).

-- Dan
0
 

Author Comment

by:renam00
ID: 7163376
I changed my program a little bit and insted of a static object, I use explicit initialization and finalization functions. I was confident but... I crash on the CoUninitialize again ! So basicly, the program do not use, create or delete any COM object at all. The "only" it does is at the begining of the program, CoInitialize is call on the main thread and before the program exits (e.g. inside the WinMain fnct) CoUninitialize is call. And sometimes it crashes. Always the same stack.
In this minimal scenario, the callback from nowhere is not possible. I don't know what to think.
0
 
LVL 22

Expert Comment

by:ambience
ID: 7163906
is it possible that you are doing multiple CoInitialize and CoUninitialize on your primary thread, although this should not be an issue but maybe you can try to reduce those calls to once per thread.

I remember some problems pertaining to that very situation, so i think its worth a try
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7164034
Check the return value from ::CoInitializeEx().  It will be S_FALSE if you are calling it a second time.  It will pass the SUCCEEDED test, but be 1)  Looking at the code that you provided, that would allow your program to CoCreateInstance the object multiple times.

In your last test did you comment out the call to CoCreateInstance?

Do you know what SXLRT233D! 1000c72e() is?

Maybe the COM object is misbehaving and doing some screwball stuff in its own DllMain.  Like what if it was instantiating a cached object of quick access.  The CoUninitialze would need to pump a bunch of messages until that object was shut down.

-- Dan
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 1500 total points
ID: 7200006
Hi renam00,
Do you have any additional questions?  Do any comments need clarification?
-- Dan
0
 

Author Comment

by:renam00
ID: 7200760
Hi Dan,

I solved the problem but I don't quite understand why : The ONLY way the intermitent crash do not hapen is when I get ride of the static object and I used explcit initialization\finalization function AND when I use OleInitialize and OleUninitialize instead of of regular function. I do not make sense since no object is created...

Anyway, I appreciated you help and suggestions, I will give you the "big reward"...

Thanks too to everybody that helped me.

renam00
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
Suggested Courses

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question