FIX: Program Crash when Connecting to Data Source from a DLL

Last reviewed: September 18, 1997
Article ID: Q118659
1.50 WINDOWS kbprg kbfixlist kbbuglist

The information in this article applies to:

   The Microsoft Foundation Classes (MFC), included with:
    - Microsoft Visual C++ for Windows, version 1.5

SYMPTOMS

A program may crash if it calls a DLL function that creates and opens a CDatabase object. This happens when two applications share the same _USRDLL DLL. It can also happen when two applications are using the _AFXDLL version of the MFC database code MFCD250.DLL or MFCD250D.DLL.

CAUSE

The MFC code uses a global static variable called "henvAllConnections" to store the ODBC environment handle (HENV), which is used by several of the ODBC API functions. The variable is defined in DBCORE.CPP as follows:

    HENV CDatabase::henvAllConnections = NULL;

This HENV variable is assigned when the first CDatabase object is created. All subsequent CDatabase objects use this same variable. This design does not work because, in the case of a DLL where a CDatabase object is created, the handle stored in henvAllConnections is used for all CDatabase objects created by all applications that call the DLL's function. ODBC allocates the memory associated with an HENV to the task. Therefore, the memory associated with the henvAllConnections handle belongs to the first application that called the DLL's function and created the first CDatabase. When the application goes away, so does the memory associated with the HENV. All other applications with CDatabases open that were created in the DLL will most likely crash.

RESOLUTION

Make sure that only one application is using the DLL or let only one application at a time call the DLL's function and create a CDatabase object. In the latter case, if an application calls the DLL's function to create a CDatabase, it must delete the CDatabase before letting another application call the DLL's function to create another CDatabase object.

Another approach is to modify the code in the DBCORE.CPP file so that the code stores and uses an HENV for each task. You can use the Windows API function GetCurrentTask() to associate a HENV with a specific task handle. You can modify the code so that every time a CDatabase is created, the code checks to see whether an HENV has been allocated and associated with the current task. If no HENV has been allocated, the modified CDatabase object allocates and associates it. You then need to create additional code that replaces all references to henvAllConnections with a function call that retrieves the correct HENV for the current task. Another technique, if it is important to have all database code in one central location, is to create an application that acts as a DDE or OLE server. The server can query the database and return results to your application.

STATUS

Microsoft has confirmed this to be a bug in the MFC for Windows, version 2.5. This bug was corrected in MFC 2.51, included in Visual C++ version 1.51.


Additional reference words: 1.50 2.50 ODBC GPF fault hang
KBCategory: kbprg kbfixlist kbbuglist
KBSubcategory: MfcDatabase
Keywords : kb16bitonly MfcDatabase kbbuglist kbfixlist kbprg
Technology : kbMfc
Version : 1.50
Platform : WINDOWS
Solution Type : kbfix


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.

Last reviewed: September 18, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.