DOCUMENT:Q185864 17-JUL-2001 [visualc] TITLE :PRB: Access Violation in ODBC Cursor Library in MFC Application PRODUCT :Microsoft C Compiler PROD/VER::5.0 OPER/SYS: KEYWORDS:kberrmsg kbDatabase kbMFC kbODBC kbVC kbGrpDSVCDB kbGrpDSMDAC kbDSupport kbMDACNoSweep ====================================================================== ------------------------------------------------------------------------------- The information in this article applies to: - Microsoft Visual C++, 32-bit Enterprise Edition, version 5.0 - Microsoft Visual C++, 32-bit Professional Edition, version 5.0 ------------------------------------------------------------------------------- SYMPTOMS ======== An MFC application that uses Open Database Connectivity (ODBC) may crash randomly on a PUSH DWORD PTR instruction in ODBC Cursor Library version 3.50.36.9. The application error is: The instruction at "0x6a9b7c1a" referenced memory at "0x026a6000". The memory could not be "read". When stepping through the assembly code in the debugger, the access violation is on a PUSH DWORD PTR instruction in Odbccr32.dll. This access violation occurs at random times. CAUSE ===== An internal Cursor Library (Odbccr32.dll) function is performing a PUSH DWORD PTR instruction instead of acquiring a byte. As a result three more bytes are being read than necessary. This occurs as parsing is performed on the SQL string that was passed to the cursor library. RESOLUTION ========== If you use the MFC database classes, there are two possible workarounds: - Do not use the cursor library. - Override the MFC code to add three spaces to the end of each SQL statement before calling the ODBC SQLPrepare() function. It might not be necessary to use the ODBC Cursor Library. If you mainly add, update, or delete records then you should use dynasets because dynasets do not use the Cursor Library and they give the best performance for these scenarios. If you are fetching data frequently, then you can use snapshots without using the Cursor Library. You can avoid using the Cursor Library by specifying FALSE for the last argument (bUseCursorLib) of CDatabase::Open(), or use the CDatabase::OpenEx() member function which doesn't load the Cursor Library by default. Use the Cursor Library where you need to modify records and need the fetching advantages of a snapshot. To use the Cursor Library, you must override the two areas in MFC where SQLPrepare() is called. You need to add three spaces to the end of the SQL string that gets passed to SQLPrepare. To do this, create a new CRecordset-derived class and perform the following steps: 1. Copy the code in the CRecordset class (present in dbcore.cpp) for the following member functions into your new CRecordset-derived class: CRecordset::Open() CRecordset::Update() CRecordset::PrepareAndExectue() CRecordset::BuildUpdateSQL() CRecordset::UpdateInsertDelete() CRecordset::Delete() 2. Make the following modifications to BuildUpdateSQL() and PrepareAndExecute() in the new CRecordset class. a. For BuildUpdateSQL(), replace this statement: AFX_ODBC_CALL(::SQLPrepare(m_hstmtUpdate, (UCHAR*)T2A((LPTSTR)(LPCTSTR)(m_strUpdateSQL), SQL_NTS)); with this code: AFX_ODBC_CALL(::SQLPrepare(m_hstmtUpdate, (UCHAR*)T2A((LPTSTR)(LPCTSTR)(m_strUpdateSQL+" ")), SQL_NTS)); This adds three spaces to the SQL statement. b. For PrepareAndExectue(), replace this statement: LPCSTR lpszWSQL = T2CA(m_strSQL); with this code: CString strSQLTmp = m_strSQL + " "; // Added three spaces. LPCSTR lpszWSQL = T2CA(strSQLTmp); STATUS ====== Microsoft is researching this problem and will post new information here in the Microsoft Knowledge Base as it becomes available. Additional query words: gpf general protection fault snapshot VC++ VC kbDatabase kbODBC kbMFC kbVC500 kbDSupport ====================================================================== Keywords : kberrmsg kbDatabase kbMFC kbODBC kbVC kbGrpDSVCDB kbGrpDSMDAC kbDSupport kbMDACNoSweep Technology : kbVCsearch kbAudDeveloper kbVC500 kbVC32bitSearch kbVC500Search Version : :5.0 Issue type : kbprb ============================================================================= THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY. Copyright Microsoft Corporation 2001.