CORRECTIF : Fuite de mémoire dans le pilote Jet ODBC avec les données SQL_NUMERIC ou SQL_C_BINARY

Ancien nº de publication de cet article : F273772
Cet article a été archivé. Il est proposé « en l'état » et ne sera plus mis à jour.
Symptômes
Lorsque vous appelez la fonction SQLBindParameter dans le pilote Jet ODBC, et que vous liez à un type de données SQL de SQL_NUMERIC ou que vous liez SQL_C_BINARY à SQL_WCHAR, une fuite de mémoire survient.

Si vous utilisez l'Analyseur de performances (PerfMon) pour visualiser le compteur Octets privés pour le processus, vous voyez une augmentation progressive mais constante de la mémoire, et la mémoire n'est pas libérée lorsque les instructions ou les connexions se terminent.
Cause
Des tampons sont utilisés au sein du pilote Jet ODBC pour aider à convertir les types de données des paramètres ODBC en types de données natifs pour le moteur de base de données Jet. Il est fait référence à ces tampons par le biais de pointeurs conservés sur le handle d'instruction, au sein des descripteurs de paramètre (IPD).

Normalement, le code vérifie si le pointeur fait déjà référence à un tampon de mémoire valide, puis utilise à nouveau le tampon, s'il existe. Toutefois, lorsque vous liez un type de données SQL_NUMERIC, ou lorsque vous liez SQL_C_BINARY à SQL_WCHAR, de la mémoire nouvelle est allouée et attribuée au pointeur sans vérification préalable, et la valeur précédente est écrasée.
Résolution
Ce problème a été résolu dans les derniers Service packs de Windows 2000 et MDAC 2.5.
  • Pour résoudre ce problème, procurez-vous le dernier Service Pack de Windows 2000. Pour plus d'informations, consultez l'article suivant dans la Base de connaissances Microsoft :
    F260910 Procédures d'obtention du dernier Service Pack de Windows 2000
  • Pour résoudre ce problème, procurez-vous le dernier Service pack de Microsoft Data Access Components 2.5. Pour plus d'informations, consultez l'article suivant dans la Base de connaissances Microsoft :
    293312 INFO : Obtention du dernier Service Pack de MDAC 2.5
La version anglaise de ce correctif doit disposer des attributs de fichier suivants ou de ceux d'une version ultérieure :
Date      Version     Taille          Nom de fichier----------------------------------------------------13.09.00  4.0.5708.0  270.608 octets  Odbcjt32.dll14.09.00  1.10.101.0  295.696 octets  Q273772_W2K_SP2_x86_en.EXE
REMARQUE : Ce correctif requiert Microsoft Data Access Components (MDAC) 2.5 Service Pack 1 (SP1) ou une version ultérieure en raison des dépendances sur les autres fichiers introduits à l'aide de MDAC 2.5 SP1. Aucun correctif n'est disponible que vous pouvez appliquer directement à MDAC 2.5.

Pour installer ce correctif sur une plate-forme Microsoft Windows 2000, exécutez le lot d'installation du correctif (Q273772_W2K_SP2_x86_en.EXE). Bien que le correctif lui-même ne dépende pas de la plate-forme, le lot d'installation du correctif a été conçu pour s'exécuter uniquement sur les plates-formes Windows 2000, et ne s'exécutera pas sur les plates-formes Microsoft Windows NT 4.0, Microsoft Windows 95, ni Microsoft Windows 98. MDAC contient des fichiers système protégés que vous pouvez remplacer uniquement par un installateur de correctif signé numériquement sous Windows 2000. Le fichier de correctif indépendant est fourni également pour que vous puissiez copier ce fichier directement sur les plates-formes Windows NT 4.0, Windows 95 ou Windows 98.


SOLUTION



Il n'existe pas de solution à ce problème.
Statut
Microsoft a confirmé l'existence de ce problème dans les produits Microsoft répertoriés au début de cet article. Ce problème a été corrigé pour la première fois dans Microsoft Data Access Components 2.5 Service Pack 2 et dans Microsoft Windows 2000 Service Pack 2.
Plus d'informations
Si vous examinez de manière périodique la mémoire dédiée au processus au cours de l'exécution du processus, vous pouvez voir un nombre croissant de 0x100000 (1048576) allocations d'octets. Si l'exécution du processus se poursuit, un dépassement de mémoire peut avoir lieu, entraînant le blocage (pas de réponse) ou l'échec du processus.

Procédure à suivre pour reproduire ce comportement



  1. Copiez le code suivant dans une application de console Microsoft Visual C++, puis compilez le code. Notez que vous pouvez avoir à changer le nom de la source de données, ainsi que l'ID et le mot de passe d'utilisateur.
    #include <windows.h>#include <sql.h>#include <sqlext.h>#include <tchar.h>#include <stdlib.h>#include <stdio.h>#define LEAK_NUMERIC 1		//Uiliser cela pour déterminer une fuite de données NUMERIC ou BINARYvoid 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,"Handle non valide !\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    	//Pas de vérification des codes de renvoi dans certains cas par soucis de        clarté.		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;	//un seul paramètre dans ce cas	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("Heures %d sélectionnées\n", i);			//printf("Enregistrements %d insérés\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);}
    REMARQUE : Vous pouvez utiliser la constante LEAK_NUMERIC pour démontrer la fuite SQL_NUMERIC ou SQL_C_BINARY.
  2. Créez une nouvelle base de données Microsoft Access vide comme spécifié par l'emplacement dans votre chaîne de connexion.
  3. Commencez l'exécution du code, puis utilisez l'Analyseur de performances pour surveiller le compteur Octets privés pour le processus.

    Notez que le compteur Octets privés augmente de manière constante au fil de l'exécution du code.
jet odbc driver odbcjt32.dll memory leak sql_numeric sql_c_binary sqlbindparameter parameters
Propriétés

ID d'article : 273772 - Dernière mise à jour : 01/10/2015 12:49:05 - Révision : 4.0

Pilote ODBC pour Access 4.0 de Microsoft, Microsoft Data Access Components 2.5, Microsoft Data Access Components 2.5 Service Pack 1

  • kbnosurvey kbarchive kbbug kbfix kbmdac250sp2fix kbwin2000presp2fix kbjet kbmdac250bug kbgrpdsvcdb kbgrpdsmdac kbmdac250sp1bug KB273772
Commentaires