Oprava: Nevracení paměti v ovladači ODBC Jet s SQL_NUMERIC nebo SQL_C_BINARY data

Překlady článku Překlady článku
ID článku: 273772 - Produkty, které se vztahují k tomuto článku.
Rozbalit všechny záložky | Minimalizovat všechny záložky

Na této stránce

Příznaky

Při volání funkce SQLBindParameter v ovladači Jet ODBC a svážete s typem dat SQL SQL_NUMERIC nebo svázat SQL_C_BINARY SQL_WCHAR, dochází k nevracení paměti.

Pokud nesdílených bajtů pro proces sledovat pomocí nástroje Sledování výkonu (PerfMon), uvidíte postupné, ale ustálených zvýšení paměti a paměť uvolněna, nejsou při ukončení příkazů nebo připojení.

Příčina

Vyrovnávací paměti se používají v rámci ovladač Jet ODBC umožňují převést na nativní datové typy pro databázový stroj Jet ODBC parametr datové typy. Vyrovnávací paměti jsou odkazovány prostřednictvím ukazatele na popisovač příkazu udržován jako část parametr popisovače (IPDs).

Kód obvykle zkontroluje zda ukazatel již odkazuje vyrovnávací paměti platné, a potom opakovaně používá vyrovnávací paměti, pokud existuje. Však při vytváření vazby datový typ SQL_NUMERIC nebo pokud vazba SQL_C_BINARY k SQL_WCHAR, nové paměti je přiděleno a přiřazeny ukazatel bez kontroly nejprve a přepsána předchozí hodnotu.

Řešení

Tento problém je vyřešen v nejnovější aktualizace service Pack pro systém Windows 2000 a součásti MDAC 2.5.
  • Tento problém vyřešíte pomocí nejnovější aktualizace service pack pro systém Windows 2000. Další informace získáte následujícím článku báze Microsoft Knowledge Base:
    260910Jak získat nejnovější aktualizaci Service Pack pro systém Windows 2000
  • Tento problém vyřešíte pomocí nejnovější aktualizace service pack pro Microsoft Data Access Components 2.5. Další informace získáte následujícím článku báze Microsoft Knowledge Base:
    293312INFORMACE: Jak získat nejnovější součásti MDAC 2.5 Service Pack
Anglická verze této opravy má následující atributy souborů nebo novější:
   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
				
Poznámka: Tato oprava hotfix vyžaduje Microsoft Data Access Components (MDAC) 2.5 Service Pack 1 (SP1) nebo novější z důvodu závislostí na jiných souborech zavedena s aktualizací SP1 pro součásti MDAC 2.5. Není k dispozici žádná oprava k dispozici, které můžete použít přímo na součásti MDAC 2.5.

Chcete-li nainstalovat tuto opravu hotfix na platformě Microsoft Windows 2000, spusťte instalační balíček opravy hotfix (Q273772_W2K_SP2_x86_en.EXE). Přestože oprava hotfix sám není závislé na platformě, instalační balíček opravy hotfix je navržena ke spouštění pouze na platformách systému Windows 2000 a nebude možné spustit v systému Microsoft Windows NT 4.0, Microsoft Windows 95 nebo Microsoft Windows 98 platformy. Součásti MDAC obsahuje systém chráněných souborů a tyto soubory můžete nahradit pouze digitálně podepsané opravy hotfix instalačním programem v systému Windows 2000. Samostatný soubor opravy hotfix je k dispozici také tak, aby tento soubor můžete zkopírovat přímo na platformách systému Windows NT 4.0, Windows 95 nebo Windows 98.


ŘEŠENÍ

Neexistuje žádné řešení tohoto problému.

Prohlášení

Společnost Microsoft potvrzuje, že se jedná o problém v produktech této společnosti, které jsou uvedeny na začátku tohoto článku. Tento problém byl poprvé opraven v Microsoft Data Access Components 2.5 Service Pack 2 a Windows 2000 Service Pack 2.

Další informace

Pokud se zkoumá paměti pro proces pravidelně během procesu spuštění se zobrazí rostoucí počet 0x100000 (1048576) přidělení bajtů. Pokud proces pokračuje, proces nakonec vyčerpá paměť a přestane reagovat (zablokuje se) nebo se nezdaří.

Kroky pro reprodukci chování

  1. Zkopírujte kód, který následuje do aplikace Microsoft Visual C++ konzoly a poté sestavit kód. Všimněte si, že budete muset změnit název zdroje dat, id uživatele a heslo.
    #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);
    
    }
    
    						
    Poznámka: Konstanta LEAK_NUMERIC lze použít k prokázání nevracení SQL_NUMERIC nebo SQL_C_BINARY.
  2. Vytvoření nové prázdné aplikace Microsoft Access databáze podle umístění v připojovací řetězec.
  3. Spustit spuštění kódu a potom pomocí nástroje Sledování výkonu sledujte čítač nesdílených bajtů pro proces.

    Všimněte si, že čítač nesdílených bajtů roste neustále je spuštěn kód.

Vlastnosti

ID článku: 273772 - Poslední aktualizace: 26. září 2005 - Revize: 2.2
Informace v tomto článku jsou určeny pro produkt:
  • Ovladač Microsoft Open Database Connectivity pro aplikaci Access 4.0
  • Microsoft Data Access Components 2.5
  • Microsoft Data Access Components 2.5 Service Pack 1
Klíčová slova: 
kbmt kbhotfixserver kbqfe kbbug kbfix kbjet kbmdac250sp2fix kbwin2000presp2fix KB273772 KbMtcs
Strojově přeložený článek
Důležité: Tento článek byl přeložen pomocí software společnosti Microsoft na strojový překlad, ne profesionálním překladatelem. Společnost Microsoft nabízí jak články přeložené překladatelem, tak články přeložené pomocí software na strojový překlad, takže všechny články ve Znalostní databázi (Knowledge Base) jsou dostupné v češtině. Překlad pomocí software na strojový překlad ale není bohužel vždy dokonalý. Obsahuje chyby ve skloňování slov, skladbě vět, nebo gramatice, podobně jako když cizinci dělají chyby při mluvení v češtině. Společnost Microsoft není právně zodpovědná za nepřesnosti, chyby nebo škody vzniklé chybami v překladu, nebo při použití nepřesně přeložených instrukcí v článku zákazníkem. Společnost Microsoft aktualizuje software na strojový překlad, aby byl počet chyb omezen na minimum.
Projděte si také anglickou verzi článku:273772

Dejte nám zpětnou vazbu

 

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