Bitten by COM

It's official: I've been spoiled by the niceties of .Net. In yesterday's IXMLHTTPRequest example, I made a very stupid mistake.

What I did is a mistake that every COM programmer should be aware of: I created a circular reference. Since COM is reference counted, circular references create memory leaks. For those who're not familiar with this particular problem (perhaps because they've never used a reference counted system), here's what happens: when object A is created, its reference count is 1. A creates object B and holds a reference to it; its reference count is also 1. B takes a reference back to A, so its reference count becomes 2. Now the original creator of A is done with it, and releases it: the count for A is now one. But because B still holds a reference to A, its count doesn't reach zero until B is destroyed. But B will not be destroyed until its own count reaches zero, which won't happen until A is destroyed. Neither A nor B ever gets destroyed, so you get a memory leak.

In my case, the event sink object held a reference to the IXMLHTTPRequest, which held a reference to the event sink. In my sample, this wasn't much of a problem since the objects would get forcably released when CoUninitialize was called, which happened only a few nanoseconds after we were done with the objects. But in a real application, this can be a problem.

The solution is fortunately very easy: cheat with the reference count. By having the event sink not call AddRef on the request, the problem disappears. And since we can ensure that the event sink object will never use request object after it's been freed, this is safe.

I've updated the sample code. In addition to this change, I've also made the reference counting of the event sink object thread safe, since it was being used on more than one thread.

Categories: Programming
Posted on: 2007-06-22 07:04 UTC.

Comments

Eric M

2007-06-27 21:48 UTC

I am trying to compile your bho, FindAsYouType, and I keep getting a compiler error: Cannot find file 'msxml6.h.' I've searched for this file and can't seem to locate it.

I'm using Visual Studio 8.
Any ideas?
Eric

Sven Groot Author comment

2007-06-29 15:43 UTC

Hi Eric,
You need to download and install the MSXML6 SDK from this page: http://www.microsoft.com/downloads/details.aspx?FamilyID=993C0BCF-3BCF-4009-BE21-27E85E1857B1&displaylang=en

Then point Visual Studio at the appropriate paths.

Eric M

2007-07-02 19:29 UTC

Oh, I guess it would help if my compiler knew where to find the files it needs...
That solved that issue. Now I get this error:
c:\documents and settings\emohs\my documents\visual studio 2005\projects\findasyoutype\findasyoutype\windows_error.h(30) : error C2664: 'FormatMessageA' : cannot convert parameter 5 from 'LPWSTR' to 'LPSTR'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
Is there a switch to allow these or is it something else I'm missing?
Sorry to be such a pain.
Thanks,
E!

Eric M

2007-07-03 22:41 UTC

Well, OK, I figured THAT out.

Now I get unresolved symbol errors from the linker, regarding _com_issue_error(...)

I can't seem to find any references to this function.

I must be missing a library or something...
If you could tell me what I'm doing wrong, I'd be most grateful.
Thanks.
Eric

Sven Groot Author comment

2007-07-04 01:12 UTC

I think that that function may come from comsuppw.lib, which contains the _bstr_t and _variant_t classes I use.

These last two questions make me curious though; are you using my project file? Since I don't see how you could run into these two problems if you are.

Eric M

2007-07-05 20:30 UTC

So, after much hair pulling I finally decided to start from scratch. I removed VS and all the SDKs, reinstalled them all, and opened up your solution file.
NOW, all those previous errors went away, but...
I get errors for 'unresolved symbols':
__imp__GetDeviceCaps...
__imp__StretchBlt...
__imp__SetStretchBltMode...
and a few others I found in gdi32.lib
__imp__RegCloseKey...
__imp__RegCreateKeyExW...
__imp__RegSetValueExW...
and others, in advapi32.lib

My Libs directory list is pointed at these files...I don't understand why the linker can't find them.

Just to clarify, I'm now using VC++Express, as I didn't want to wait six hours for VS8Pro to install (who needs ATL anyway?)

Still trying...
Eric

Add comment

Comments are closed for this post. Sorry.

Latest posts

Categories

Archive

Syndication

RSS Subscribe