| Bug #2987 | Memory leak in SQLConnect incase of failure | ||
|---|---|---|---|
| Submitted: | 26 Feb 2004 22:52 | Modified: | 21 Jul 2004 18:59 |
| Reporter: | Srinivas B.S.S | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | Connector / ODBC | Severity: | S2 (Serious) |
| Version: | 3.51.06 | OS: | Solaris (Solaris 2.8 (sparc)) |
| Assigned to: | Timothy Smith | CPU Architecture: | Any |
[27 Feb 2004 1:38]
Srinivas B.S.S
Updating to specify that I have used unixODBC as driver manager.
[29 Jun 2004 0:27]
Timothy Smith
Verified against 3.51.07 w/ unixODBC on FreeBSD 5.2
[18 Jul 2004 22:23]
Peter Harvey
I ran the test program using "top" to monitor memory usage. I was NOT able to create the problem in my default working environment; - Fedore Core 2 - unixODBC 2.2.9 (latest download) - MyODBC 3.51 (latest from source repository) - MySQL 4.0.20 I tried using valgrind but failed to get it to work on Fedora Core 2. I eventually got it to work on SuSE 9.0. I eventually tried the following and was able to see the problem. - SuSE 9.0 - unixODBC 2.2.6 (binary from SuSE Linux distro) - MyODBC 3.51 (latest from source repository) - MySQL 4.0.20 I used valgrind to verify what was pretty much obvious at this point - that the memory leak was in unixODBC. I then replaced unixODBC 2.2.6 with unixODBC 2.2.9 and the leak was gone. So the leak is in unixODBC and the solution is to use unixODBC 2.2.9 or better. I did NOT verify this on "Solaris 2.8 (sparc)" but it should solve the problem there as well.
[21 Jul 2004 18:59]
Timothy Smith
I tested on Linux w/ the latest MyODBC and unixODBC 2.2.9, and the bug leak is no longer there.

Description: There seems to be a memory leak in SQLConnect call incase of failure. The following is the case that I am using to confirm this: for( i < 100000 ) { call SQLConnect() with non-existant server (with valid datasource in odbc.ini) } I have observed memory growth from 3k to 52MB How to repeat: Write a simple program to call SQLConnect with invalid mysql server or use the following program: *************************************************************** #include <stdlib.h> #include <stdio.h> #include <time.h> #include "sql.h" #include "sqlext.h" #include "sqltypes.h" SQLHENV hEnv; // Handle ODBC environment long retc; // result of functions SQLHDBC hCon; // Handle connection SQLHANDLE hStmt; // Statement handle char V_OD_stat[10]; // Status SQL SQLINTEGER V_OD_err,V_OD_rowanz,V_OD_id; SQLSMALLINT V_OD_mlen,V_OD_colanz; char V_OD_msg[200],V_OD_buffer[200]; int main(int argc,char *argv[]) { int count = 0; // Allocate env handle retc=SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&hEnv); if ((retc != SQL_SUCCESS) && (retc != SQL_SUCCESS_WITH_INFO)) { printf("Error AllocHandle\n"); exit(1); } retc=SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); if ((retc != SQL_SUCCESS) && (retc != SQL_SUCCESS_WITH_INFO)) { printf("Error SetEnv\n"); SQLFreeHandle(SQL_HANDLE_ENV, hEnv); exit(1); } // Allocate connection handle retc = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hCon); if ((retc != SQL_SUCCESS) && (retc != SQL_SUCCESS_WITH_INFO)) { printf("Error AllocHDB %d\n",retc); SQLFreeHandle(SQL_HANDLE_ENV, hEnv); exit(1); } for( int i=0; i<=100000; i++ ) { // Try to connect retc = SQLConnect(hCon, (SQLCHAR*) "abc", SQL_NTS, (SQLCHAR*) "abc", SQL_NTS, (SQLCHAR*) "abc", SQL_NTS); if ((retc != SQL_SUCCESS) && (retc != SQL_SUCCESS_WITH_INFO)) { SQLGetDiagRec(SQL_HANDLE_DBC, hCon,1, (SQLCHAR*)V_OD_stat, &V_OD_err, (SQLCHAR*)V_OD_msg,100,&V_OD_mlen); printf("%s (%d)\n",V_OD_msg,V_OD_err); } if( retc == SQL_SUCCESS ) { printf( "Disconnecting \n"); SQLDisconnect(hCon); } } printf( "See the memory size now (before exiting):\n" ); getchar(); SQLFreeHandle(SQL_HANDLE_DBC,hCon); SQLFreeHandle(SQL_HANDLE_ENV, hEnv); return(0); } ***************************************************************