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

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
Este artigo foi arquivado. Este artigo é oferecido "tal como está" e deixará de ser actualizado.
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 leakvoid 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_NUMERICchar* szCreateTable = "CREATE TABLE LeakTable (val1 long)";#elsechar* szCreateTable = "CREATE TABLE LeakTable (val1 varchar(10))";#endifvoid 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.
Jet odbc controlador odbcjt32.dll fuga sql_numeric sql_c_binary sqlbindparameter parâmetros da memória

Aviso: Este artigo foi traduzido automaticamente

Propriedades

ID do Artigo: 273772 - Última Revisão: 01/10/2015 12:49:10 - Revisão: 2.2

Controlador Microsoft Open Database Connectivity para Access 4.0, Microsoft Data Access Components 2.5, Microsoft Data Access Components 2.5 Service Pack 1

  • kbnosurvey kbarchive kbmt kbhotfixserver kbqfe kbbug kbfix kbjet kbmdac250sp2fix kbwin2000presp2fix KB273772 KbMtpt
Comentários