0

My application uses MS Access mdb files because of legacy reasons. It connects to the database using ADO with the following connection string:

Provider=Microsoft.Jet.OLEDB.4.0;Persist Security Info=False;Data Source=Dummy.mdb

Recently I started porting my application to 64 bit. Because of that Jet OLEDB provider is not available on 64 bit systems I used ACE OLEDB provider with the following connection string:

Provider=Microsoft.ACE.OLEDB.12.0;Persist Security Info=False;Data Source=Dummy.mdb

The application also uses MS XML DOM to work with XML files. Sometimes the 64 bit version crashes with access violation exception in SysFreeString which is called from one of the MS XML wrapper methods. The 32 bit version does not have these problems. I distilled the problem into the tester applicaiton.

#define _WIN32_WINNT 0x0501

#include <stdio.h>
#include <windows.h>
#include <process.h>
#include <conio.h>
#include <ObjBase.h>

#import <msxml6.dll>
#import <msado15.dll> rename("EOF", "EndOfFile")

using namespace ADODB;

bool s_bRepeat = true;

unsigned __stdcall XmlThreadFunc(void*)
{
  CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  MSXML2::IXMLDOMDocumentPtr l_pXMLDom;
  l_pXMLDom.CreateInstance(__uuidof(DOMDocument), NULL, CLSCTX_INPROC_SERVER);
  l_pXMLDom->async = VARIANT_FALSE;
  MSXML2::IXMLDOMElementPtr l_pRoot = l_pXMLDom->createElement("root");
  l_pXMLDom->appendChild(l_pRoot);
  unsigned int l_nCnt = 0;
  while (s_bRepeat)
  {
    if (0 == l_nCnt++ % 1000)
    {
      printf(".");
    }
    l_pRoot->setAttribute("test", "Test1");
    Sleep(0);
  }
  CoUninitialize();
  _endthreadex(0);
  return 0;
} 

unsigned __stdcall DbThreadFunc(void*)
{
  CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  _ConnectionPtr l_pConnection;
  l_pConnection.CreateInstance(__uuidof(Connection));
#ifdef _WIN64
  LPCSTR l_cszConnectStr = "Provider=Microsoft.ACE.OLEDB.12.0;Persist Security Info=False;Data Source=Dummy.mdb";
#else
  LPCSTR l_cszConnectStr = "Provider=Microsoft.Jet.OLEDB.4.0;Persist Security Info=False;Data Source=Dummy.mdb";
#endif
  while (s_bRepeat)
  {
    l_pConnection->Open(l_cszConnectStr, "", "", adConnectUnspecified);
    Sleep(1000);
    printf("(");
    l_pConnection->Close();
    printf(")");
  }
  CoUninitialize();
  _endthreadex(0);
  return 0;
} 

int main()
{
  HANDLE l_hXmlThread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, &XmlThreadFunc, NULL, 0, NULL));
  HANDLE l_hDbThread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, &DbThreadFunc, NULL, 0, NULL));
  _getch();
  s_bRepeat = false;
  HANDLE l_Handles[2] = { l_hXmlThread, l_hDbThread };
  WaitForMultipleObjects(2, l_Handles, TRUE, INFINITE);
  CloseHandle(l_hXmlThread);
  CloseHandle(l_hDbThread);
  return 0;
}

The crash call stack is the following:

OLEAUT32!SysFreeString
TestCrash64Lean!_bstr_t::Data_t::_Free
TestCrash64Lean!_bstr_t::Data_t::~Data_t
TestCrash64Lean!_bstr_t::Data_t::`scalar deleting destructor'
TestCrash64Lean!_bstr_t::Data_t::Release
TestCrash64Lean!_bstr_t::_Free
TestCrash64Lean!_bstr_t::~_bstr_t
TestCrash64Lean!MSXML2::IXMLDOMElement::setAttribute
TestCrash64Lean!XmlThreadFunc
MSVCR80D!_callthreadstartex
MSVCR80D!_threadstartex
kernel32!BaseThreadInitThunk
ntdll!RtlUserThreadStart

At the crash the DB thread is always in the following state:

MSVCR90!memset
mso!Ordinal4118
mso!Ordinal7994
mso!MsoUninitOffice
ACECORE
ACECORE
ACEOLEDB!DllGetClassObject
ACEOLEDB!DllGetClassObject
ACEOLEDB!DllGetClassObject
ACEOLEDB!DllGetClassObject
oledb32!CAcm::FinalRelease
oledb32!ATL::CComPolyObject<CDCM>::~CComPolyObject<CDCM>
oledb32!ATL::CComPolyObject<CDCM>::Release
oledb32!CDCMCreator::DestroyResource
comsvcs!CHolder::SafeDispenserDriver::DestroyResource
comsvcs!CHolder::ProcessDestroyList
comsvcs!CHolder::FreeResource
oledb32!CDCMCreator::ReleaseResource
oledb32!CDPO::ReturnDCMToPool
oledb32!CDPO::FinalRelease
oledb32!ATL::CComPolyObject<CDPO>::`scalar deleting destructor'
oledb32!ATL::CComPolyObject<CDPO>::Release
msado15!CConnection::_Close
msado15!CConnection::Close
TestCrash64Lean!ADODB::Connection15::Close
TestCrash64Lean!DbThreadFunc
MSVCR80D!_callthreadstartex
MSVCR80D!_threadstartex
kernel32!BaseThreadInitThunk
ntdll!RtlUserThreadStart

I found that as a workaround if I keep one open connection to some empty database file, I can open and close connections to actual database files and the application does not crash. Anyway I would rather understand the actual cause of the crash. I would appreciate any suggestions.

My configuration is the following:

Microsoft Visual Studio 2005 Version 8.0.50727.4039 (QFE.050727-4000)
Windows Server 2008 R2 Standard 64 bit
Processor: Intel(R) Xeon(R) E5645 @ 2.40GHz
Memory: 16.0 GB

4

1 回答 1

0

看起来这是来自 Microsoft Access Database Engine 2010 Redistributable 的 ACE OLEDB 提供程序的问题。从 Microsoft Access 2013 运行时切换到提供程序解决了该问题。

于 2015-07-16T15:38:35.480 回答