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

Traduções deste artigo Traduções deste artigo
ID do artigo: 273772 - Exibir os produtos aos quais esse artigo se aplica.
Expandir tudo | Recolher tudo

Neste artigo

Sintomas

Quando você chamar a função SQLBindParameter no driver ODBC Jet, e quando você vincula a um tipo de dados SQL do SQL_NUMERIC ou quando você vincula SQL_C_BINARY a SQL_WCHAR, ocorre um vazamento de memória.

Se você usar o Monitor de desempenho (PerfMon) para bytes particulares para o processo de inspeção, você vê uma memória gradual mas estável aumentar e a memória não é liberada quando as instruções ou conexões fechar.

Causa

Buffers são usados no driver ODBC Jet para ajudar a converter os tipos de dados ODBC parâmetro tipos de dados nativo para o mecanismo de banco de dados Jet. Esses buffers são referenciados através de ponteiros mantidos no identificador de instrução, como parte de descritores de parâmetro (IPDs).

Normalmente, o código verifica se o ponteiro já faz referência a um buffer de memória válido e, em seguida, reutiliza o buffer se ele existir. No entanto, ao vincular um tipo de dados SQL_NUMERIC, ou ao ligar SQL_C_BINARY a SQL_WCHAR, nova memória é alocada e atribuída ao ponteiro sem verificação-lo primeiro e o valor anterior será substituído.

Resolução

Esse problema é corrigido no service packs mais recentes para o Windows 2000 e MDAC 2.5.
  • Para resolver esse problema, obtenha o service pack mais recente para o Windows 2000. Para obter informações adicionais, clique no número abaixo para ler o artigo na Base de dados de Conhecimento da Microsoft:
    260910Como obter o Service Pack mais recente do Windows 2000
  • Para resolver esse problema, obtenha o service pack mais recente para o Microsoft Data Access Components 2.5. Para obter informações adicionais, clique no número abaixo para ler o artigo na Base de dados de Conhecimento da Microsoft:
    293312INFO: Como obter o último MDAC 2.5 Service Pack
A versão em inglês dessa correção deve ter os seguintes atributos de arquivo 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
				
Observação : esse hotfix requer Microsoft Data Access Components (MDAC) 2.5 Service Pack 1 (SP1) ou posterior, devido às dependências em outros arquivos do introduzido com o MDAC 2.5 SP1. Não há nenhuma correção disponíveis que você pode aplicar diretamente para o MDAC 2.5.

Para instalar esse hotfix em uma plataforma Microsoft Windows 2000, execute o pacote de instalador de hotfix (Q273772_W2K_SP2_x86_en.EXE). Embora o hotfix se não for dependente de plataforma, o hotfix de instalador foi projetado para ser executado somente em plataformas Windows 2000 e não será executado no Microsoft Windows NT 4.0, Microsoft Windows 95 ou plataformas Microsoft Windows 98. MDAC contém arquivos de arquivo protegido do sistema e você só pode substituir esses arquivos, um instalador do hotfix assinadas digitalmente no Windows 2000. O arquivo de hotfix autônomo é fornecido também para que você pode copiar esse arquivo diretamente para plataformas Windows NT 4.0, Windows 95 ou Windows 98.


SOLUÇÃO ALTERNATIVA

Não há nenhuma solução alternativa para esse problema.

Situação

A Microsoft confirmou que este é um problema nos produtos da Microsoft listados no começo deste artigo. Esse problema foi corrigido primeiro no Microsoft Data Access Components 2.5 Service Pack 2 e Microsoft Windows 2000 Service Pack 2.

Mais Informações

Se você examinar a memória para o processo periodicamente enquanto executa o processo, você verá um número crescente de 0 x 100000 (1048576) alocações de byte. Se o processo continuar a executar, o processo eventualmente fica sem memória e pára de responder (trava) ou falha.

Etapas para reproduzir o problema

  1. Copie o código a seguir em um aplicativo de console do Microsoft Visual C++ e, em seguida, compile o código. Por favor, observe que talvez seja necessário alterar o nome de fonte de dados, identificação de usuário e a senha.
    #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);
    
    }
    
    						
    Observação : você pode usar a constante LEAK_NUMERIC para demonstrar o SQL_NUMERIC ou SQL_C_BINARY vazamento.
  2. Crie um novo banco de Microsoft Access dados em branco como especificado pela localização sua seqüência de conexão.
  3. Iniciar a execução do código e use desempenho do sistema para observar o contador Private Bytes para o processo.

    Observe que o contador Private Bytes aumenta com firmeza enquanto o código está sendo executado.

Propriedades

ID do artigo: 273772 - Última revisão: segunda-feira, 26 de setembro de 2005 - Revisão: 2.2
A informação contida neste artigo aplica-se a:
  • Driver 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 traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes 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