I was tracking down a error in one of the command line apps that I use to save web.config settings over upgrades. It was a strange error, If I stepped through the code, everything executed correctly, but I would get an access violation when I left a specific method call. The fun part was that all of the code in that method call executed normally. The app is written in Delphi 2007 and is Win32 unmanaged code. The code looked something like this:
function TSaveConfig.UpdateWebConfig(const srcfile, destfile: string): boolean;
fsrcDoc, fDestDoc: IXMLDocument;
result := true;
fsrcDoc := LoadXMLDocument(srcFile);
fDestDoc := LoadXMLDocument(DestFile);
UpdateNode(fsrcDoc, fDestDoc, 'configuration\system.web\httpRuntime', 'executionTimeout', '', '');
UpdateNode(fsrcDoc, fDestDoc, 'configuration\system.web\sessionState', 'timeout', '', '');
if fDestdoc.Modified then begin
Not much to it. My Spidey sense started tingling at the calls to CoInitialize/CoUninitialize. CoInitialize is needed to initialize the COM library on the current thread. And COM is needed because I am using MS XML COM objects to work with the web.config files. I was initializing COM, using COM, then uninitializing COM. The problem was that I was using interfaces to the COM objects and Delphi is managing the lifetime of interfaces. At the end of the method call, those objects go out of scope and Delphi calls their cleanup code. In my case this happens after the the call to CoUninitialize. My IXMLDocument interfaces were being garbage collected by the Delphi runtime and they were referencing a COM library that had been already closed.
In this case, the fix was easy. I just moved the calls to CoInitialize/CoUninitialize to the code that calls UpdateWebConfig. Once I did that, my odd little access violation was fixed. That's one of those bugs that seems obvious after you fix it. What clued me in to what was going on was a post by Chris Bensen that explained it all. Thanks Chris!