CORRECÇÃO: Fuga de memória no controlador de ODBC Jet com SQL_NUMERIC ou SQL_C_BINARY dados

Traduções de Artigos Traduções de Artigos
Artigo: 273772 - Ver produtos para os quais este artigo se aplica.
Expandir tudo | Reduzir tudo

Nesta página

Sintomas

Quando chamar a função de SQLBindParameter no controlador de ODBC Jet e ligar a um tipo de dados SQL do SQL_NUMERIC ou quando ligar SQL_C_BINARY SQL_WCHAR, ocorre uma fuga de memória.

Se utilizar o Monitor de desempenho (PerfMon) para ver os bytes privados para o processo, verá uma memória gradual mas constante aumentar e a memória não é libertada quando as instruções ou ligações fechado.

Causa

Memórias intermédias são utilizadas no controlador de ODBC Jet para ajudar a converter os tipos de dados do parâmetro ODBC para tipos de dados original para o motor de base de dados Jet. Estas memórias intermédias são referenciadas através de ponteiros mantidos na alça de instrução, como parte de descritores de parâmetro (IPDs).

Normalmente, o código verifica se o ponteiro já referencia uma válido de memória intermédia e, em seguida, reutiliza a memória intermédia, caso exista. No entanto, quando a ligação um tipo de dados SQL_NUMERIC, ou quando vincular SQL_C_BINARY a SQL_WCHAR, nova memória é atribuída e atribuída para o ponteiro sem verificar primeiro e o valor anterior será substituído.

Resolução

Este problema foi corrigido no service packs mais recentes para o Windows 2000 e MDAC 2.5.
  • Para resolver este problema, obtenha o service pack mais recente do Windows 2000. Para obter informações adicionais, clique no número de artigo que se segue para visualizar o artigo na Microsoft Knowledge Base:
    260910Como obter o Service Pack mais recente do Windows 2000
  • Para resolver este problema, obtenha o service pack mais recente do Microsoft Data Access Components 2.5. Para obter informações adicionais, clique no número de artigo que se segue para visualizar o artigo na Microsoft Knowledge Base:
    293312INFO: Como obter o mais recente MDAC 2.5 Service Pack
A versão inglesa desta correcção deverá ter os seguintes atributos de ficheiro ou posteriores:
   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
				
Nota : esta correcção requer o Microsoft Data Access Components (MDAC) 2.5 Service Pack 1 (SP1) ou posterior devido a dependências noutros ficheiros introduzida com o MDAC 2.5 SP1. Não existe nenhuma correcção disponível que pode aplicar directamente para o MDAC 2.5.

Para instalar esta correcção numa plataforma Microsoft Windows 2000, execute o pacote de instalação correcção (Q273772_W2K_SP2_x86_en.EXE). Apesar da correcção se não estiver dependente da plataforma, o pacote de instalação correcção concebido para ser executado apenas em plataformas Windows 2000 e não será executado no Microsoft Windows NT 4.0, Microsoft Windows 95 ou Microsoft Windows 98 plataformas. MDAC contém ficheiros de ficheiros protegidos do sistema e só pode substituir esses ficheiros por um programa de instalação correcção assinado digitalmente no Windows 2000. O ficheiro de correcção autónomo é fornecido também para que possa copiar esse ficheiro directamente para plataformas Windows NT 4.0, Windows 95 ou Windows 98.


SOLUÇÃO

Não existe nenhuma solução para este problema.

Ponto Da Situação

A Microsoft confirmou que este é um problema nos produtos da Microsoft listados no início deste artigo. Este problema foi corrigido pela primeira vez no Microsoft Data Access Components 2.5 Service Pack 2 e Microsoft Windows 2000 Service Pack 2.

Mais Informação

Se examinar a memória para o processo periodicamente enquanto executa o processo, verá um número crescente de 0x100000 (1048576) byte atribuições. Se o processo continua a ser executado, o processo de eventualmente fica sem memória e deixa de responder (não reage) ou falha.

Passos para reproduzir o comportamento

  1. Copie o código que se segue numa aplicação de consola do Microsoft Visual C++ e, em seguida, compilar o código. Por favor note que poderá ter alterar o nome da origem de dados, o id de utilizador e palavra-passe.
    #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);
    
    }
    
    						
    Nota : pode utilizar a constante LEAK_NUMERIC para demonstrar o SQL_NUMERIC ou SQL_C_BINARY fuga.
  2. Crie uma nova base de Microsoft Access dados em branco tal como especificado pela localização na cadeia da ligação.
  3. Inicie a executar o código e, em seguida, utilizar o Monitor de desempenho para ver o contador Private Bytes para o processo.

    Tenha em atenção que o contador Private Bytes ultrapassa modo firme enquanto o código está em execução.

Propriedades

Artigo: 273772 - Última revisão: 26 de setembro de 2005 - Revisão: 2.2
A informação contida neste artigo aplica-se a:
  • Controlador Microsoft Open Database Connectivity para Access 4.0
  • Microsoft Data Access Components 2.5
  • Microsoft Data Access Components 2.5 Service Pack 1
Palavras-chave: 
kbmt kbhotfixserver kbqfe kbbug kbfix kbjet kbmdac250sp2fix kbwin2000presp2fix KB273772 KbMtpt
Tradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine translation ou MT), não tendo sido portanto revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática? erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 273772

Submeter comentários

 

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