FIX: 記憶體遺漏資料 SQL_NUMERIC 或 SQL_C_BINARY Jet ODBC 驅動程式中

文章翻譯 文章翻譯
文章編號: 273772 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

在此頁中

徵狀

當您將 Jet ODBC 驅動程式中呼叫 SQLBindParameter 函式,以及當您將繫結至 SQL 資料型別 SQL_NUMERIC 或當您將 SQL_C_BINARY 繫結至 SQL_WCHAR,就會發生記憶體遺漏。

如果要監看私用位元組處理程序中使用效能監視器 (PerfMon),您看到逐漸但穩定的記憶體增加,與陳述式或連線關閉時,不會釋放記憶體。

發生的原因

緩衝區內 Jet ODBC 驅動程式可用來協助將 ODBC 參數資料型別轉換成 Jet 資料庫引擎的原生資料型別。這些緩衝區會透過此陳述式控制代碼上維護的參數描述元 (IPDs) 一部分的指標參考。

通常,程式碼會查看指標已經參考有效的記憶體緩衝區,然後再重新使用緩衝區,如果存在的話。不過,繫結 SQL_NUMERIC 資料型別時或繫結 SQL_C_BINARY 至 SQL_WCHAR 時新的記憶體已配置並指派給指標而不先,檢查並覆寫先前的值。

解決方案

在最新的 Service Pack 的 Windows 2000 和 MDAC 2.5 中解決此問題。
  • 如果要解決這個問題,取得最新的 Service Pack 為 Windows 2000。如需詳細資訊按一下 [下面的文件編號,檢視 「 Microsoft 知識庫 」 中的發行項]:
    260910如何取得最新的 Windows 2000 Service Pack
  • 如果要解決這個問題,取得最新的 Service Pack 的 Microsoft 資料存取元件 2.5。如需詳細資訊按一下 [下面的文件編號,檢視 「 Microsoft 知識庫 」 中的發行項]:
    293312資訊: 如何取得最新的 MDAC 2.5 Service Pack
此修正程式的英文版應該具有下列檔案屬性或更新版本:
   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
				
注意: 這個 Hotfix 需要 Microsoft 資料存取元件 (MDAC) 2.5 Service Pack 1 (SP1),或因為其他檔案的相依性較晚引入 MDAC 2.5 SP1。可用您可以直接將套用至 MDAC 2.5 沒有修正程式。

若要在 Microsoft Windows 2000 平台上安裝此 Hotfix,執行 Hotfix 安裝程式封裝 (Q273772_W2K_SP2_x86_en.EXE)。雖然 Hotfix 本身不是平台相依,Hotfix 安裝程式套件設計只能在 Windows 2000 平台上執行,並將不會在 Microsoft Windows NT 4.0、 Microsoft Windows 95 或 Microsoft Windows 98 平台上執行。MDAC 包含系統檔案保護檔案,而您只可以在 Windows 2000 上的數位簽章的 Hotfix 安裝程式取代這些檔案。獨立 Hotfix 檔案係也使您可以將該檔案複製到 Windows NT 4.0、 Windows 95 或 Windows 98 的平台直接。


因應措施

這個問題沒有解決方法。

狀況說明

Microsoft 已確認這是在本文開頭所列之 Microsoft 產品中的問題。這個問題,首先已經在 Microsoft 資料存取元件 2.5 Service Pack 2 和 Microsoft Windows 2000 Service Pack 2 中獲得修正。

其他相關資訊

如果您檢查記憶體供處理程序會定期在處理程序執行時,您會看到越來越多的 0x100000 (1048576) 位元組配置。如果程序會繼續執行,處理程序最後記憶體用完,並停止回應 (擱置) 或失敗。

重製行為的步驟

  1. 複製到 Microsoft Visual C++ 主控台應用程式後面的程式碼,並編譯程式碼。請注意您可能需要變更資料來源名稱、 使用者 ID 和密碼。
    #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);
    
    }
    
    						
    注意: 您可以使用 LEAK_NUMERIC 常數來示範 [SQL_NUMERIC] 或 [SQL_C_BINARY 遺漏。
  2. 建立新空白的 Microsoft Access 資料庫所指定的位置連接字串中。
  3. 開始執行程式碼,然後使用 [監看處理序的私用位元組計數器的 [效能監視器。

    請注意,私用位元組 」 計數器持續上升執行程式碼時。

屬性

文章編號: 273772 - 上次校閱: 2005年9月26日 - 版次: 2.2
這篇文章中的資訊適用於:
  • Microsoft Open Database Connectivity Driver for Access 4.0
  • Microsoft Data Access Components 2.5
  • Microsoft Data Access Components 2.5 Service Pack 1
關鍵字:?
kbmt kbhotfixserver kbqfe kbbug kbfix kbjet kbmdac250sp2fix kbwin2000presp2fix KB273772 KbMtzh
機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:273772
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。

提供意見

 

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