Update: Speicherleck in Jet ODBC-Treiber mit SQL_NUMERIC oder SQL_C_BINARY Daten

SPRACHE AUSWÄHLEN SPRACHE AUSWÄHLEN
Artikel-ID: 273772 - Produkte anzeigen, auf die sich dieser Artikel bezieht
Alles erweitern | Alles schließen

Auf dieser Seite

Problembeschreibung

Wenn Sie die Funktion SQLBindParameter in dem Jet ODBC-Treiber aufrufen und Sie an eine SQL-Datentyp SQL_NUMERIC oder beim Binden von SQL_C_BINARY an SQL_WCHAR binden, tritt ein Speicherverlust auf.

Wenn Sie den Systemmonitor (PerfMon), verwenden um die privaten Bytes für den Prozess zu überwachen, sehen Sie eine stufenweise aber stetigen Speicher erhöhen und der Speicher ist nicht freigegeben, wenn die Anweisungen oder Verbindungen schließen.

Ursache

Puffer werden in dem Jet ODBC-Treiber verwendet, damit die ODBC-Parameter-Datentypen in systemeigenen Datentypen für die Jet-Datenbankmodul zu konvertieren. Dieser Puffer werden über Zeiger auf das Anweisungshandle verwaltet, als Teil der Sicherheitsbeschreibungen Parameter (IPDs) verwiesen.

Normalerweise prüft der Code, wenn der Zeiger verweist bereits auf einen gültigen Speicherpuffer und dann den Puffer, wiederverwendet sofern vorhanden. Jedoch beim SQL_NUMERIC Datentyp zu binden oder beim Binden von SQL_C_BINARY an SQL_WCHAR, neuen Speicher reserviert und der Zeiger zugewiesen, ohne zuerst überprüfen, und der vorherige Wert überschrieben.

Lösung

Dieses Problem wird in den neuesten Service Packs für Windows 2000 und MDAC 2.5 behoben.
  • Installieren Sie das neueste Service Pack für Windows 2000, um dieses Problem zu beheben. Weitere Informationen finden Sie die folgende KB-Artikelnummer:
    260910Wie Sie das neueste Service Pack für Windows 2000 erhalten
  • Installieren Sie das neueste Servicepack für Microsoft Data Access Components 2.5, um dieses Problem zu beheben. Weitere Informationen finden Sie die folgende KB-Artikelnummer:
    293312INFO: Wie erhalten Sie die neueste MDAC 2.5 Servicepack
Die englische Version dieses Updates müsste die folgenden Dateiattribute oder höher:
   Date        Version       Size              File name    
   ---------------------------------------------------------------------
   09/13/00    4.0.5708.0    270,608 bytes    Odbcjt32.dll
   09/14/00    1.10.101.0    295,696 bytes    Q273772_W2K_SP2_x86_en.EXE
				
Hinweis : dieser Hotfix erfordert Microsoft Data Access Components (MDAC) 2.5 Service Pack 1 (SP1) oder höher aufgrund von Abhängigkeiten von anderen Dateien mit MDAC 2.5 SP1 eingeführt. Es gibt kein Update verfügbar, die Sie direkt zu MDAC 2.5 anwenden können.

Führen Sie das Hotfix-Installer-Paket (Q273772_W2K_SP2_x86_en.EXE), um diesen Hotfix auf einem Microsoft Windows 2000-Plattform zu installieren. Der Hotfix selbst ist, zwar nicht plattformabhängige wird das Hotfix-Installer-Paket ist nur auf Windows 2000-Plattformen vorgesehen und wird auf Microsoft Windows NT 4.0, Microsoft Windows 95 oder Microsoft Windows 98-Plattformen nicht ausgeführt. MDAC enthält Datei geschützte Systemdateien, und Sie können diese Dateien nur ersetzen, indem eine digital signierte Hotfix-Installer unter Windows 2000. Die eigenständige Hotfix-Datei wird sowie bereitgestellt, sodass Sie die Datei direkt in Windows NT 4.0, Windows 95 oder Windows 98-Plattformen kopieren können.


PROBLEMUMGEHUNG

Es gibt keine Problemumgehung für dieses Problem.

Status

Microsoft hat bestätigt, dass es sich hierbei um ein Problem bei den in diesem Artikel genannten Microsoft-Produkten handelt. Dieses Problem wurde erstmals im Microsoft Data Access Components 2.5 Service Pack 2 und Microsoft Windows 2000 Service Pack 2.

Weitere Informationen

Den Speicher für den Prozess in regelmäßigen Abständen während der Prozess ausgeführt wird, Sie feststellen eine steigende Anzahl von 0 x 100000 (1048576) Bytezuweisungen. Wenn der Prozess ausgeführt weiterhin, das schließlich zuwenig Arbeitsspeicher ausgeführt wird und nicht mehr reagiert (hängt) oder fehlschlägt.

Schritte zum Reproduzieren des Verhaltens

  1. Kopieren Sie den Code, der in eine Microsoft Visual C++-Konsolenanwendung folgt, und kompilieren Sie den Code. Beachten Sie, dass Sie möglicherweise ändern Sie den Namen der Datenquelle, Benutzer-Id und das Kennwort müssen.
    #include <windows.h>
    #include <sql.h>
    #include <sqlext.h>
    #include <tchar.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    
    #define LEAK_NUMERIC 1		//Use this to determine NUMERIC or BINARY leak
    
    
    void HandleError(SQLHANDLE	hHandle, SQLSMALLINT hType, RETCODE RetCode)
    {
    	SQLSMALLINT	iRec = 0;
    	SQLINTEGER	iError;
    	TCHAR		szMessage[1000];
    	TCHAR		szState[SQL_SQLSTATE_SIZE];
    
    
    	if (RetCode == SQL_INVALID_HANDLE)
    	{
    		fprintf(stderr,"Invalid handle!\n");
    		return;
    	}
    
    	while (SQLGetDiagRec(hType,
    			 hHandle,
    			 ++iRec,
    			 (SQLCHAR *)szState,
    			 &iError,
    			 (SQLCHAR *)szMessage,
    			 (SQLSMALLINT)(sizeof(szMessage) / sizeof(TCHAR)),
    			 (SQLSMALLINT *)NULL) == SQL_SUCCESS)
    	{
    		fprintf(stderr,TEXT("[%5.5s] %s (%d)\n"),szState,szMessage,iError);
    	}
    
    }
    
    
    char* szConnStringIn = "Driver={Microsoft Access Driver (*.mdb)};DBQ=E:\\JetLeak\\TestDatabase.mdb";
    char* szDropTable = "DROP TABLE LeakTable";
    //char* szInsertStatement = "INSERT INTO LeakTable VALUES (?)";
    char* szSelectStatement = "SELECT * FROM LeakTable WHERE val1 = ?";
    const int nParamCount = 1; 
    
    #if LEAK_NUMERIC
    char* szCreateTable = "CREATE TABLE LeakTable (val1 long)";
    #else
    char* szCreateTable = "CREATE TABLE LeakTable (val1 varchar(10))";
    #endif
    
    
    
    void main(int argc, char* argv[])
    {
    	SQLHENV henv;
    	SQLHDBC hdbc;
    	SQLHSTMT hstmt;
    	SQLRETURN nstatus;
    
    	char szConnStringOut[1024];
    	SQLSMALLINT cbConnOut;
    	SQLINTEGER status[nParamCount];
    
    #if LEAK_NUMERIC
    	SQLCHAR szParam[nParamCount][10] = {"12345"};
    #else
    	BYTE szParam[nParamCount][10] = {0x31,0x33,0x34,0x39};
    #endif
        
    	//Not checking the return codes in some cases for clarity.
    	
    	nstatus = SQLAllocHandle(SQL_HANDLE_ENV,NULL,&henv);
    	nstatus = SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER) SQL_OV_ODBC3,0);
    	nstatus = SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc);
    
    	nstatus = SQLDriverConnect(hdbc,
    			NULL,
    			(SQLCHAR*) szConnStringIn,
    			SQL_NTS,
    			(SQLCHAR*) szConnStringOut,
    			sizeof (szConnStringOut),
    			&cbConnOut,
    			SQL_DRIVER_COMPLETE);
    							
    	if (nstatus != SQL_SUCCESS && nstatus != SQL_SUCCESS_WITH_INFO)
    	{
    		HandleError(hdbc,SQL_HANDLE_DBC,nstatus);
    		return;
    	}
    
    	nstatus = SQLAllocHandle(SQL_HANDLE_STMT,hdbc,&hstmt);	
    
    	nstatus = SQLExecDirect(hstmt, (SQLCHAR*) szDropTable, SQL_NTS);
    	nstatus = SQLExecDirect(hstmt, (SQLCHAR*) szCreateTable, SQL_NTS);
    
    	if (!SQL_SUCCEEDED(nstatus))
    	{
    		HandleError(hstmt,SQL_HANDLE_STMT,nstatus);
    	}
    
    	int i;
    	//only one parameter in this case
    	for (i=0; i < nParamCount; i++)
    	{
    		status[i] = SQL_NTS;
    
    
    
    #if LEAK_NUMERIC
    		nstatus = SQLBindParameter(hstmt,
    			i+1,
    			SQL_PARAM_INPUT,
    			SQL_C_CHAR,	
    			SQL_NUMERIC, 
    			10, 
    			0,
    			szParam[i],
    			10,
    			&status[i]);
    #else
    
    		nstatus = SQLBindParameter(hstmt,
    			i+1,
    			SQL_PARAM_INPUT,
    			SQL_C_BINARY,	
    			SQL_WCHAR,
    			10, 
    			0,
    			szParam[i],
    			10,
    			&status[i]);
    #endif
    	
    	
    	}
    
    	nstatus = SQLPrepare(hstmt,(SQLCHAR*) szSelectStatement, SQL_NTS);
    	if (nstatus != SQL_SUCCESS)
    	{
    		HandleError(hstmt,SQL_HANDLE_STMT,nstatus);
    	}
    
    	for (i=0; i < 100000; i++)
    	{
    		if (i % 100 == 0)
    		{
    			printf("Selected %d times\n", i);
    			//printf("Inserted %d records\n", i);
    			Sleep(100);
    		}
    		nstatus = SQLExecute(hstmt);
    		if (nstatus != SQL_SUCCESS)
    		{
    			HandleError(hstmt,SQL_HANDLE_STMT,nstatus);
    		}
    
    		SQLFreeStmt(hstmt, SQL_CLOSE);
    	}
    
    	nstatus = SQLExecDirect(hstmt, (SQLCHAR*) "DELETE FROM LeakTable", SQL_NTS);
    	if (nstatus != SQL_SUCCESS)
    	{
    		HandleError(hstmt,SQL_HANDLE_STMT,nstatus);
    	}
    
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    	SQLDisconnect(hdbc);
    
    }
    
    						
    Hinweis : können Sie die LEAK_NUMERIC-Konstante SQL_NUMERIC oder SQL_C_BINARY Speicherverlust veranschaulichen.
  2. Erstellen Sie eine neue leere Microsoft Access-Datenbank wie angegeben durch die Position in der Verbindungszeichenfolge.
  3. Starten der Code ausgeführt wird, und dann mithilfe des Systemmonitors um den Indikator Private Bytes für den Prozess zu überwachen.

    Beachten Sie, dass der Indikator Private Bytes stetig zunimmt, während der Code ausgeführt wird.

Eigenschaften

Artikel-ID: 273772 - Geändert am: Montag, 26. September 2005 - Version: 2.2
Die Informationen in diesem Artikel beziehen sich auf:
  • Microsoft Open Database Connectivity-Treiber für Access 4.0
  • Microsoft Data Access Components 2.5
  • Microsoft Data Access Components 2.5 Service Pack 1
Keywords: 
kbmt kbhotfixserver kbqfe kbbug kbfix kbjet kbmdac250sp2fix kbwin2000presp2fix KB273772 KbMtde
Maschinell übersetzter Artikel
Wichtig: Dieser Artikel wurde maschinell und nicht von einem Menschen übersetzt. Die Microsoft Knowledge Base ist sehr umfangreich und ihre Inhalte werden ständig ergänzt beziehungsweise überarbeitet. Um Ihnen dennoch alle Inhalte auf Deutsch anbieten zu können, werden viele Artikel nicht von Menschen, sondern von Übersetzungsprogrammen übersetzt, die kontinuierlich optimiert werden. Doch noch sind maschinell übersetzte Texte in der Regel nicht perfekt, insbesondere hinsichtlich Grammatik und des Einsatzes von Fremdwörtern sowie Fachbegriffen. Microsoft übernimmt keine Gewähr für die sprachliche Qualität oder die technische Richtigkeit der Übersetzungen und ist nicht für Probleme haftbar, die direkt oder indirekt durch Übersetzungsfehler oder die Verwendung der übersetzten Inhalte durch Kunden entstehen könnten.
Den englischen Originalartikel können Sie über folgenden Link abrufen: 273772
Microsoft stellt Ihnen die in der Knowledge Base angebotenen Artikel und Informationen als Service-Leistung zur Verfügung. Microsoft übernimmt keinerlei Gewährleistung dafür, dass die angebotenen Artikel und Informationen auch in Ihrer Einsatzumgebung die erwünschten Ergebnisse erzielen. Die Entscheidung darüber, ob und in welcher Form Sie die angebotenen Artikel und Informationen nutzen, liegt daher allein bei Ihnen. Mit Ausnahme der gesetzlichen Haftung für Vorsatz ist jede Haftung von Microsoft im Zusammenhang mit Ihrer Nutzung dieser Artikel oder Informationen ausgeschlossen.

Ihr Feedback an uns

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com