Help Please! ADO Access Violation in VC++ 
Author Message
 Help Please! ADO Access Violation in VC++

Hi,
This is partial a repost.  Originally I thought the problem was resolved but
it turns out not to be the case and now I am even more confused.

I am suffering from an access violation when ADO is used from global object
exported from MFC extensions DLL (VC++)  and have no idea how to resolve it.

I am in the process of converting a VC++ legacy application from DAO to ADO.
The way this application works is it has a class that encapsulates the
database access defined in a DLL and a global object of this type is
exported from the DLL and used as a singleton.  All calls to the database
are made via this object.  I discovered that when I added an ADO
_ConnectionPtr  member to database encapsulation object and called
CreateInstance() it caused an access violation in MSDART.DLL when the
application exit.

I dont understand why this is.  I did discover that if right after the call
to CreateInstance() I added a call to AddRef() the access violation goes
away in some cases as it does in the test project.   (see code below) in my
full application it seems only to go away if I actually call execute on the
connection pointer.   I am at a loss and  would truly appreciate if somebody
could explain this to me.  I have reproduced this in a minimal standard MFC
project and will be glad to send it to anybody or you can follow the
instructions bellow to reproduce yourself.

Any help would be greatly appreciated (code sample follows signature)
Thanks
  Joey

To reproduce the error:
* Create an MFC extension DLL project add the CMyDB class to it.  (Minimal
code is at bottom of message) .
* Create a standard MFC wizard app SDI app in the doc object include the
"MyDB.h"  and add a call       TheDB.ForceDllLoad(5,6); to the
OnNewDocument()

Run the app.  When you exit you should receive the access violation.

// MyDB.h: interface for the CMyDB class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_MYDB_H__B670CD08_CCE1_4C15_9FE1_D27E59A6F4FC__INCLUDED_)
#define AFX_MYDB_H__B670CD08_CCE1_4C15_9FE1_D27E59A6F4FC__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <comdef.h>
#import "E:\Program Files\Common Files\System\ADO\msado15.dll"
rename_namespace("NSADO") rename("EOF", "EndOfFile")
#include "icrsint.h"
using namespace NSADO;

inline void TestHR( HRESULT _hr )
   { if FAILED(_hr) _com_issue_error(_hr); }

class AFX_EXT_CLASS CMyDB
{
public:
      int ForceDllLoad(int a,int b);
      CMyDB();
      virtual ~CMyDB();
      _ConnectionPtr  m_pDenXDBADO;

Quote:
};

// define the DataBase access class to be global
// defined as external in .h and
// defined in .cpp ( so it will
// be alocated only once).

extern CMyDB AFX_EXT_CLASS TheDB;

#endif //
!defined(AFX_MYDB_H__B670CD08_CCE1_4C15_9FE1_D27E59A6F4FC__INCLUDED_)

// MyDB.cpp: implementation of the CMyDB class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MyDB.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

CMyDB  AFX_EXT_CLASS TheDB;      // DataBase defined as a global.

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMyDB::CMyDB()
{
      CoInitialize(NULL);

      try {
            HRESULT hr =
pDenXDBADO.CreateInstance( __uuidof( NSADO::Connection ) );
            TestHR(hr);
//  Uncomment next line to somtimes prevent access violation.
//          m_pDenXDBADO.AddRef();
            if (SUCCEEDED(hr))
            {
                  CString connectStr;

connectStr.Format(_T("Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=db1.mdb;Persist Security Info=False"));

                  hr = m_pDenXDBADO->Open(
                        (LPCSTR) connectStr,
                        _bstr_t(L""),
                        _bstr_t(L""),
                        adModeShareDenyNone);
                  TestHR(hr);
            }

      }
      catch (_com_error &e)
      {
            CString str;
            str.Format(

"Error:%08lx.\nErrorMessage:%s.\nSource:%s.\nDescription:%s.\n",
                  e.Error(), e.ErrorMessage(),(LPCTSTR) _bstr_t(e.Source()),
                  (LPCTSTR) _bstr_t(e.Description()));
            AfxMessageBox(str);

    }

Quote:
}

CMyDB::~CMyDB()
{
      CoUninitialize( );  // <-- this seems to make no diffrence

Quote:
}

// Silly do nothing functin that forces the DLL to be loaded
// and global object to be initialized.
int CMyDB::ForceDllLoad(int a, int b)
{
      return a+b;
Quote:
}



Thu, 29 May 2003 20:20:21 GMT  
 Help Please! ADO Access Violation in VC++
Hello,

1. At the first glance, I noticed that you don't close the connection
explicitly. When you open a connection explicitly, *always* close it
explicitly too! Don't rely on garbage collection objects. So in the
destructor of CMyDB() class, first check to see whether m_pDenXDBADO is
NULL. If it's not, then call the Close method of the Connection object, if
and only if the connection is already opened:

if(m_pDenXDBADO)
   if(m_pDenXDBADO->State == adStateOpen)
   {
    HRESULT hr = m_pDenXDBADO->Close();
    if(FAILED(hr))
     ASSERT(FALSE);

    m_pDenXDBADO = NULL;
   }

2. At the next glance, please assign m_pDenXDBADO pointer to the null, i.e.
m_pDenXDBADO = NULL before you call ::CoUninitialize() method, as I did at
the above function. This prevents the internal _Release function to be
called, which of course, in some circumstances makes unpredictable results.

3. Make sure that CMyDB class is not called from 2 different threads at the
same time. If it's called, you've to synchronize some certain points of your
class using one of those 4 available sync MFC classes, or else, it may end
up in unpredictable results, such as exceptions in "RPCRT4.DLL",
"MSCRVT.DLL" or the like!

4. Always try to catch unexpected exceptions, using the following macro:
catch(....) i.e.:

try
{
//open the database

Quote:
}

 catch(_com_error &e)
{
//whatever error message handling
Quote:
}

catch(...)
{
//take unhandled exceptions here!

Quote:
}

I sincerely hope that you never see that damn message box again!

HTH,
Mehdi
--
Got a question about modems? Take a look at http://www.modemmania.com
"The important thing is not to stop questioning. -- Albert Einstein"


Quote:
> Hi,
> This is partial a repost.  Originally I thought the problem was resolved
but
> it turns out not to be the case and now I am even more confused.

> I am suffering from an access violation when ADO is used from global
object
> exported from MFC extensions DLL (VC++)  and have no idea how to resolve
it.

> I am in the process of converting a VC++ legacy application from DAO to
ADO.
> The way this application works is it has a class that encapsulates the
> database access defined in a DLL and a global object of this type is
> exported from the DLL and used as a singleton.  All calls to the database
> are made via this object.  I discovered that when I added an ADO
> _ConnectionPtr  member to database encapsulation object and called
> CreateInstance() it caused an access violation in MSDART.DLL when the
> application exit.

> I don't understand why this is.  I did discover that if right after the
call
> to CreateInstance() I added a call to AddRef() the access violation goes
> away in some cases as it does in the test project.   (see code below) in
my
> full application it seems only to go away if I actually call execute on
the
> connection pointer.   I am at a loss and  would truly appreciate if
somebody
> could explain this to me.  I have reproduced this in a minimal standard
MFC
> project and will be glad to send it to anybody or you can follow the
> instructions bellow to reproduce yourself.

> Any help would be greatly appreciated (code sample follows signature)
> Thanks
>   Joey

> To reproduce the error:
> * Create an MFC extension DLL project add the CMyDB class to it.  (Minimal
> code is at bottom of message) .
> * Create a standard MFC wizard app SDI app in the doc object include the
> "MyDB.h"  and add a call       TheDB.ForceDllLoad(5,6); to the
> OnNewDocument()

> Run the app.  When you exit you should receive the access violation.

> // MyDB.h: interface for the CMyDB class.
> //
> //////////////////////////////////////////////////////////////////////

> #if !defined(AFX_MYDB_H__B670CD08_CCE1_4C15_9FE1_D27E59A6F4FC__INCLUDED_)
> #define AFX_MYDB_H__B670CD08_CCE1_4C15_9FE1_D27E59A6F4FC__INCLUDED_

> #if _MSC_VER > 1000
> #pragma once
> #endif // _MSC_VER > 1000

> #include <comdef.h>
> #import "E:\Program Files\Common Files\System\ADO\msado15.dll"
> rename_namespace("NSADO") rename("EOF", "EndOfFile")
> #include "icrsint.h"
> using namespace NSADO;

> inline void TestHR( HRESULT _hr )
>    { if FAILED(_hr) _com_issue_error(_hr); }

> class AFX_EXT_CLASS CMyDB
> {
> public:
>       int ForceDllLoad(int a,int b);
>       CMyDB();
>       virtual ~CMyDB();
>       _ConnectionPtr  m_pDenXDBADO;

> };

> // define the DataBase access class to be global
> // defined as external in .h and
> // defined in .cpp ( so it will
> // be alocated only once).

> extern CMyDB AFX_EXT_CLASS TheDB;

> #endif //
> !defined(AFX_MYDB_H__B670CD08_CCE1_4C15_9FE1_D27E59A6F4FC__INCLUDED_)

> // MyDB.cpp: implementation of the CMyDB class.
> //
> //////////////////////////////////////////////////////////////////////

> #include "stdafx.h"
> #include "MyDB.h"

> #ifdef _DEBUG
> #undef THIS_FILE
> static char THIS_FILE[]=__FILE__;
> #define new DEBUG_NEW
> #endif

> CMyDB  AFX_EXT_CLASS TheDB;      // DataBase defined as a global.

> //////////////////////////////////////////////////////////////////////
> // Construction/Destruction
> //////////////////////////////////////////////////////////////////////

> CMyDB::CMyDB()
> {
>       CoInitialize(NULL);

>       try {
>             HRESULT hr =
> pDenXDBADO.CreateInstance( __uuidof( NSADO::Connection ) );
>             TestHR(hr);
> //  Uncomment next line to somtimes prevent access violation.
> //          m_pDenXDBADO.AddRef();
>             if (SUCCEEDED(hr))
>             {
>                   CString connectStr;

> connectStr.Format(_T("Provider=Microsoft.Jet.OLEDB.4.0;Data
> Source=db1.mdb;Persist Security Info=False"));

>                   hr = m_pDenXDBADO->Open(
>                         (LPCSTR) connectStr,
>                         _bstr_t(L""),
>                         _bstr_t(L""),
>                         adModeShareDenyNone);
>                   TestHR(hr);
>             }

>       }
>       catch (_com_error &e)
>       {
>             CString str;
>             str.Format(

> "Error:%08lx.\nErrorMessage:%s.\nSource:%s.\nDescription:%s.\n",
>                   e.Error(), e.ErrorMessage(),(LPCTSTR)

_bstr_t(e.Source()),

- Show quoted text -

Quote:
>                   (LPCTSTR) _bstr_t(e.Description()));
>             AfxMessageBox(str);

>     }

> }

> CMyDB::~CMyDB()
> {
>       CoUninitialize( );  // <-- this seems to make no diffrence
> }

> // Silly do nothing functin that forces the DLL to be loaded
> // and global object to be initialized.
> int CMyDB::ForceDllLoad(int a, int b)
> {
>       return a+b;
> }



Fri, 30 May 2003 00:50:25 GMT  
 Help Please! ADO Access Violation in VC++
Hello,

1. At the first glance, I noticed that you don't close the connection
explicitly. When you open a connection explicitly, *always* close it
explicitly too! Don't rely on garbage collection objects. So in the
destructor of CMyDB() class, first check to see whether m_pDenXDBADO is
NULL. If it's not, then call the Close method of the Connection object, if
and only if the connection is already opened:

if(m_pDenXDBADO)
   if(m_pDenXDBADO->State == adStateOpen)
   {
    HRESULT hr = m_pDenXDBADO->Close();
    if(FAILED(hr))
     ASSERT(FALSE);

    m_pDenXDBADO = NULL;
   }

2. At the next glance, please assign m_pDenXDBADO pointer to the null, i.e.
m_pDenXDBADO = NULL before you call ::CoUninitialize() method, as I did at
the above function. This prevents the internal _Release function to be
called, which of course, in some circumstances makes unpredictable results.

3. Make sure that CMyDB class is not called from 2 different threads at the
same time. If it's called, you've to synchronize some certain points of your
class using one of those 4 available sync MFC classes, or else, it may end
up in unpredictable results, such as exceptions in "RPCRT4.DLL",
"MSCRVT.DLL" or the like!

4. Always try to catch unexpected exceptions, using the following macro:
catch(....) i.e.:

try
{
//open the database

Quote:
}

 catch(_com_error &e)
{
//whatever error message handling
Quote:
}

catch(...)
{
//take unhandled exceptions here!

Quote:
}

I sincerely hope that you never see that damn message box again!

HTH,
Mehdi
--
Got a question about modems? Take a look at http://www.modemmania.com
"The important thing is not to stop questioning. -- Albert Einstein"


Quote:
> Hi,
> This is partial a repost.  Originally I thought the problem was resolved
but
> it turns out not to be the case and now I am even more confused.

> I am suffering from an access violation when ADO is used from global
object
> exported from MFC extensions DLL (VC++)  and have no idea how to resolve
it.

> I am in the process of converting a VC++ legacy application from DAO to
ADO.
> The way this application works is it has a class that encapsulates the
> database access defined in a DLL and a global object of this type is
> exported from the DLL and used as a singleton.  All calls to the database
> are made via this object.  I discovered that when I added an ADO
> _ConnectionPtr  member to database encapsulation object and called
> CreateInstance() it caused an access violation in MSDART.DLL when the
> application exit.

> I don't understand why this is.  I did discover that if right after the
call
> to CreateInstance() I added a call to AddRef() the access violation goes
> away in some cases as it does in the test project.   (see code below) in
my
> full application it seems only to go away if I actually call execute on
the
> connection pointer.   I am at a loss and  would truly appreciate if
somebody
> could explain this to me.  I have reproduced this in a minimal standard
MFC
> project and will be glad to send it to anybody or you can follow the
> instructions bellow to reproduce yourself.

> Any help would be greatly appreciated (code sample follows signature)
> Thanks
>   Joey

> To reproduce the error:
> * Create an MFC extension DLL project add the CMyDB class to it.  (Minimal
> code is at bottom of message) .
> * Create a standard MFC wizard app SDI app in the doc object include the
> "MyDB.h"  and add a call       TheDB.ForceDllLoad(5,6); to the
> OnNewDocument()

> Run the app.  When you exit you should receive the access violation.

> // MyDB.h: interface for the CMyDB class.
> //
> //////////////////////////////////////////////////////////////////////

> #if !defined(AFX_MYDB_H__B670CD08_CCE1_4C15_9FE1_D27E59A6F4FC__INCLUDED_)
> #define AFX_MYDB_H__B670CD08_CCE1_4C15_9FE1_D27E59A6F4FC__INCLUDED_

> #if _MSC_VER > 1000
> #pragma once
> #endif // _MSC_VER > 1000

> #include <comdef.h>
> #import "E:\Program Files\Common Files\System\ADO\msado15.dll"
> rename_namespace("NSADO") rename("EOF", "EndOfFile")
> #include "icrsint.h"
> using namespace NSADO;

> inline void TestHR( HRESULT _hr )
>    { if FAILED(_hr) _com_issue_error(_hr); }

> class AFX_EXT_CLASS CMyDB
> {
> public:
>       int ForceDllLoad(int a,int b);
>       CMyDB();
>       virtual ~CMyDB();
>       _ConnectionPtr  m_pDenXDBADO;

> };

> // define the DataBase access class to be global
> // defined as external in .h and
> // defined in .cpp ( so it will
> // be alocated only once).

> extern CMyDB AFX_EXT_CLASS TheDB;

> #endif //
> !defined(AFX_MYDB_H__B670CD08_CCE1_4C15_9FE1_D27E59A6F4FC__INCLUDED_)

> // MyDB.cpp: implementation of the CMyDB class.
> //
> //////////////////////////////////////////////////////////////////////

> #include "stdafx.h"
> #include "MyDB.h"

> #ifdef _DEBUG
> #undef THIS_FILE
> static char THIS_FILE[]=__FILE__;
> #define new DEBUG_NEW
> #endif

> CMyDB  AFX_EXT_CLASS TheDB;      // DataBase defined as a global.

> //////////////////////////////////////////////////////////////////////
> // Construction/Destruction
> //////////////////////////////////////////////////////////////////////

> CMyDB::CMyDB()
> {
>       CoInitialize(NULL);

>       try {
>             HRESULT hr =
> pDenXDBADO.CreateInstance( __uuidof( NSADO::Connection ) );
>             TestHR(hr);
> //  Uncomment next line to somtimes prevent access violation.
> //          m_pDenXDBADO.AddRef();
>             if (SUCCEEDED(hr))
>             {
>                   CString connectStr;

> connectStr.Format(_T("Provider=Microsoft.Jet.OLEDB.4.0;Data
> Source=db1.mdb;Persist Security Info=False"));

>                   hr = m_pDenXDBADO->Open(
>                         (LPCSTR) connectStr,
>                         _bstr_t(L""),
>                         _bstr_t(L""),
>                         adModeShareDenyNone);
>                   TestHR(hr);
>             }

>       }
>       catch (_com_error &e)
>       {
>             CString str;
>             str.Format(

> "Error:%08lx.\nErrorMessage:%s.\nSource:%s.\nDescription:%s.\n",
>                   e.Error(), e.ErrorMessage(),(LPCTSTR)

_bstr_t(e.Source()),

- Show quoted text -

Quote:
>                   (LPCTSTR) _bstr_t(e.Description()));
>             AfxMessageBox(str);

>     }

> }

> CMyDB::~CMyDB()
> {
>       CoUninitialize( );  // <-- this seems to make no diffrence
> }

> // Silly do nothing functin that forces the DLL to be loaded
> // and global object to be initialized.
> int CMyDB::ForceDllLoad(int a, int b)
> {
>       return a+b;
> }



Fri, 30 May 2003 02:55:42 GMT  
 Help Please! ADO Access Violation in VC++
Thanks for the response.  Unfortunetly it dosn't work  I have created a new
project including the changes and posted it to:
http://www.deskalarm.com/callAdoviaDll.zip

m_pDenXDBADO->Close(); now causes and access viloation no matter what I do.
AddRef no longer makes any diffrence.
Any additonlay help would be appricialted.

While a catch(...) would oboiulsly stop the app form crshing on the access
violation it won't help it work :)

  Joey


Quote:
> Hello,

> 1. At the first glance, I noticed that you don't close the connection
> explicitly. When you open a connection explicitly, *always* close it
> explicitly too! Don't rely on garbage collection objects. So in the
> destructor of CMyDB() class, first check to see whether m_pDenXDBADO is
> NULL. If it's not, then call the Close method of the Connection object, if
> and only if the connection is already opened:

> if(m_pDenXDBADO)
>    if(m_pDenXDBADO->State == adStateOpen)
>    {
>     HRESULT hr = m_pDenXDBADO->Close();
>     if(FAILED(hr))
>      ASSERT(FALSE);

>     m_pDenXDBADO = NULL;
>    }

> 2. At the next glance, please assign m_pDenXDBADO pointer to the null,
i.e.
> m_pDenXDBADO = NULL before you call ::CoUninitialize() method, as I did at
> the above function. This prevents the internal _Release function to be
> called, which of course, in some circumstances makes unpredictable
results.

> 3. Make sure that CMyDB class is not called from 2 different threads at
the
> same time. If it's called, you've to synchronize some certain points of
your
> class using one of those 4 available sync MFC classes, or else, it may end
> up in unpredictable results, such as exceptions in "RPCRT4.DLL",
> "MSCRVT.DLL" or the like!

> 4. Always try to catch unexpected exceptions, using the following macro:
> catch(....) i.e.:

> try
> {
> //open the database
> }
>  catch(_com_error &e)
> {
> //whatever error message handling
> }
> catch(...)
> {
> //take unhandled exceptions here!
> }

> I sincerely hope that you never see that damn message box again!

> HTH,
> Mehdi
> --
> Got a question about modems? Take a look at http://www.modemmania.com
> "The important thing is not to stop questioning. -- Albert Einstein"



Sat, 31 May 2003 19:58:57 GMT  
 Help Please! ADO Access Violation in VC++
Hi,

I'm guessing that the accessviolation occures due to the COM libraries being
uninitialized BEFORE the last call to ADO. When the program reaches the
destructor for your MyDB class, the MFC framework has already called
CoUninitialize(). This will cause an accessviolation. Add some code to make
sure that the MyDB object is destroyed before this happens, i.e. in
ExitInstance() in the MFC application object.

Arild Bakken
System Developer
---
Inmeta AS - http://www.inmeta.com


Quote:
> Thanks for the response.  Unfortunetly it dosn't work  I have created a
new
> project including the changes and posted it to:
> http://www.deskalarm.com/callAdoviaDll.zip

> m_pDenXDBADO->Close(); now causes and access viloation no matter what I
do.
> AddRef no longer makes any diffrence.
> Any additonlay help would be appricialted.

> While a catch(...) would oboiulsly stop the app form crshing on the access
> violation it won't help it work :)

>   Joey



> > Hello,

> > 1. At the first glance, I noticed that you don't close the connection
> > explicitly. When you open a connection explicitly, *always* close it
> > explicitly too! Don't rely on garbage collection objects. So in the
> > destructor of CMyDB() class, first check to see whether m_pDenXDBADO is
> > NULL. If it's not, then call the Close method of the Connection object,
if
> > and only if the connection is already opened:

> > if(m_pDenXDBADO)
> >    if(m_pDenXDBADO->State == adStateOpen)
> >    {
> >     HRESULT hr = m_pDenXDBADO->Close();
> >     if(FAILED(hr))
> >      ASSERT(FALSE);

> >     m_pDenXDBADO = NULL;
> >    }

> > 2. At the next glance, please assign m_pDenXDBADO pointer to the null,
> i.e.
> > m_pDenXDBADO = NULL before you call ::CoUninitialize() method, as I did
at
> > the above function. This prevents the internal _Release function to be
> > called, which of course, in some circumstances makes unpredictable
> results.

> > 3. Make sure that CMyDB class is not called from 2 different threads at
> the
> > same time. If it's called, you've to synchronize some certain points of
> your
> > class using one of those 4 available sync MFC classes, or else, it may
end
> > up in unpredictable results, such as exceptions in "RPCRT4.DLL",
> > "MSCRVT.DLL" or the like!

> > 4. Always try to catch unexpected exceptions, using the following macro:
> > catch(....) i.e.:

> > try
> > {
> > file://open the database
> > }
> >  catch(_com_error &e)
> > {
> > file://whatever error message handling
> > }
> > catch(...)
> > {
> > file://take unhandled exceptions here!
> > }

> > I sincerely hope that you never see that damn message box again!

> > HTH,
> > Mehdi
> > --
> > Got a question about modems? Take a look at http://www.modemmania.com
> > "The important thing is not to stop questioning. -- Albert Einstein"



Sat, 31 May 2003 21:26:44 GMT  
 Help Please! ADO Access Violation in VC++
Thanks for the response.  Unfortunetly it dosn't work  I have created a new
project including the changes and posted it to:
http://www.deskalarm.com/callAdoviaDll.zip

m_pDenXDBADO->Close(); now causes and access viloation no matter what I do.
AddRef no longer makes any diffrence.
Any additonlay help would be appricialted.

While a catch(...) would oboiulsly stop the app form crshing on the access
violation it won't help it work :)

  Joey



Mon, 02 Jun 2003 16:27:03 GMT  
 
 [ 6 post ] 

 Relevant Pages 

1. Help Please! ADO Access Violation in VC++

2. Access Violation when ADO is used from global object exported from MFC extensions DLL (VC++)

3. Access Violation using ADO in VC++

4. Access Violation when ADO is used from global object exported from MFC extensions DLL (VC++)

5. Please help me, IsBadReadPtr and Access violation

6. PostMessage from DLL causes access violations, help please

7. Please help: why gives me an Access Violation

8. PLEASE help solve Access Violation problems! (Getting Desperate)

9. PLEASE help solve Access Violation problems! (Getting Desperate)

10. Please help: why gives me an Access Violation

11. Please help: why gives me an Access Violation

12. Open Connection Access Violation for ADO in ATL COM

 

 
Powered by phpBB® Forum Software