REVISIÓN: Pérdida de memoria en el controlador ODBC de Jet con SQL_NUMERIC o SQL_C_BINARY datos

Seleccione idioma Seleccione idioma
Id. de artículo: 273772 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

En esta página

Síntomas

Cuando llame a la función SQLBindParameter en el controlador ODBC de Jet y cuando se enlaza a un tipo de datos SQL de SQL_NUMERIC o cuando se enlaza SQL_C_BINARY a SQL_WCHAR, se produce una pérdida de memoria.

Si utiliza al Monitor de rendimiento (PerfMon) para inspeccionar los bytes privados para el proceso, verá una memoria gradual pero estable aumentar y la memoria no se liberará al cerrar las instrucciones o conexiones.

Causa

Búferes se utilizan en el controlador ODBC de Jet para ayudar convierta a los tipos de datos del parámetro ODBC de los tipos de datos nativo para el motor de base de datos Jet. Estos búferes se identifican mediante punteros que se mantiene en el controlador de instrucción, como parte de los descriptores de parámetro (IPDs).

Normalmente, el código comprueba si el puntero ya hace referencia a un búfer de memoria válida y, a continuación, reutiliza el búfer si existe. Sin embargo, cuando enlace un tipo de datos SQL_NUMERIC o enlazar SQL_C_BINARY a SQL_WCHAR, asigna memoria nueva y asignado al puntero sin comprobación de primero y se sobrescribe el valor anterior.

Solución

Este problema se corrigió en los service Pack más recientes para Windows 2000 y MDAC 2.5.
  • Para resolver este problema, obtenga el Service Pack más reciente de Windows 2000. Para obtener información adicional, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
    260910Cómo obtener el Service Pack más reciente para Windows 2000
  • Para resolver este problema, obtenga el service pack más reciente para Microsoft Data Access Components 2.5. Para obtener información adicional, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
    293312INFO: Cómo obtener la más reciente de MDAC 2.5 Service Pack
La versión en inglés de esta revisión debe tener los atributos de archivo siguientes o 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 : este hotfix requiere Microsoft Data Access Components (MDAC) 2.5 Service Pack 1 (SP1) o posterior debido a las dependencias en otros archivos de introducidos con MDAC 2.5 Service Pack 1. No hay ninguna revisión disponible que puede aplicar directamente a MDAC 2.5.

Para instalar este hotfix en una plataforma de Microsoft Windows 2000, ejecute el paquete de instalador de revisiones (Q273772_W2K_SP2_x86_en.EXE). Aunque la revisión sí no es dependiente de la plataforma, el paquete de instalador de revisiones está diseñado para ejecutarse sólo en plataformas de Windows 2000 y no se ejecutará en Microsoft Windows NT 4.0, Microsoft Windows 95 o plataformas de Microsoft Windows 98. MDAC contiene los archivos del archivo protegido de sistema y puede reemplazar sólo los archivos por un instalador de revisión firmado digitalmente en Windows 2000. El archivo de revisión independiente se proporciona así para que pueda copiar dicho archivo directamente en las plataformas Windows NT 4.0, Windows 95 o Windows 98.


SOLUCIÓN

No se conoce ninguna solución temporal para este problema.

Estado

Microsoft ha confirmado que se trata de un problema de los productos de Microsoft enumerados en la sección "La información de este artículo se refiere a:" de este artículo. Este problema se corrigió por primera vez en Microsoft Data Access Components 2.5 Service Pack 2 y Microsoft Windows 2000 Service Pack 2.

Más información

Si examina la memoria para el proceso periódicamente durante el proceso se ejecuta, verá un número creciente de 0 x 100000 (1048576) asignaciones de bytes. Si continúa el proceso ejecutar, los proceso que finalmente se queda sin memoria y deja de responder (se bloquea) o se produce un error.

Pasos para reproducir este comportamiento

  1. Copie el código que sigue en una aplicación de consola de Microsoft Visual C++ y, a continuación, compile el código. Por favor, tenga en cuenta que puede necesitar cambiar el nombre de origen de datos, el id de usuario y la contraseña.
    #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 : puede utilizar la constante LEAK_NUMERIC para demostrar la SQL_NUMERIC o SQL_C_BINARY pérdida.
  2. Crear una nueva base de Microsoft Access datos en blanco según lo especificado por la ubicación en la cadena de conexión.
  3. Iniciar la ejecución del código y utilice a Monitor de rendimiento para ver el contador bytes privados para el proceso.

    Tenga en cuenta que el contador bytes privados aumenta continuamente mientras se ejecuta el código.

Propiedades

Id. de artículo: 273772 - Última revisión: lunes, 26 de septiembre de 2005 - Versión: 2.2
La información de este artículo se refiere a:
  • Microsoft Open Database Connectivity Driver for Access 4.0
  • Microsoft Data Access Components 2.5
  • Microsoft Data Access Components 2.5 Service Pack 1
Palabras clave: 
kbmt kbhotfixserver kbqfe kbbug kbfix kbjet kbmdac250sp2fix kbwin2000presp2fix KB273772 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 273772

Enviar comentarios

 

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