Unix Technical Forum

Memory Leak in getting blob's

This is a discussion on Memory Leak in getting blob's within the Informix forums, part of the Database Server Software category; --> Hi, I'm retrieving blobs from my 9.40.FC4 server. This I'm doing with an Borland C++ Builder application with connects ...


Go Back   Unix Technical Forum > Database Server Software > Informix

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 04-20-2008, 08:12 AM
Bart Huls
 
Posts: n/a
Default Memory Leak in getting blob's

Hi,

I'm retrieving blobs from my 9.40.FC4 server. This I'm doing with an
Borland C++ Builder application with connects to the database with an ODBC
connection.

During the retrieving of the Blob the program exe is growing. When you look
at the software it looks quit straight forward and is has no memory leaks
(also tested by some college's).
My conclusion is that it must be the driver which is causing the memory leak
problem.

Has someone the same experience or has someone found a solution for this
problem, please let me know.

Kind Regards,

Bart Huls


Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #2 (permalink)  
Old 04-20-2008, 08:12 AM
Jonathan Leffler
 
Posts: n/a
Default Re: Memory Leak in getting blob's

Bart Huls wrote:
> I'm retrieving blobs from my 9.40.FC4 server. This I'm doing with an
> Borland C++ Builder application with connects to the database with an ODBC
> connection.
>
> During the retrieving of the Blob the program exe is growing. When you look
> at the software it looks quit straight forward and is has no memory leaks
> (also tested by some college's).


Which colleges? Or did you mean colleagues?

> My conclusion is that it must be the driver which is causing the memory leak
> problem.


I admire your confidence. Are you ensuring that you are releasing the
blob memory correctly? How are you releasing the blob memory? If you
don't know the answer to either of these questions, I would beg to
differ with your conclusion.

> Has someone the same experience or has someone found a solution for this
> problem, please let me know.


Understanding how your C++ application is handling the memory for the
blobs retrieved will let us know whether the problem is in the way you
are driving the ODBC driver or in the driver itself. If it were me
doing the C++ coding, I'd be moderately confident that the leak was in
my code -- to be convinced otherwise, I'd have created a darned good
short test case demonstrating that the leak is outside my control.
And when i submitted it, I'd still 3/4 expect to be told 'You
overlooked this obvious point'.

--
Jonathan Leffler #include <disclaimer.h>
Email: jleffler@earthlink.net, jleffler@us.ibm.com
Guardian of DBD::Informix v2003.04 -- http://dbi.perl.org/
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 04-20-2008, 08:12 AM
Bart Huls
 
Posts: n/a
Default Re: Memory Leak in getting blob's

Hi Jonathan,

Ok here it goes....
I tried it several ways lowlevel:
This program produces in the loop a memory leak.It "leaks" by the blob size.
Maybe I'm doing something wrong (and also Borland/ODBCExpress etc...) but I
doubt this.
Can you provide me some code which indicates that the retrieving of a blob
is not an driver problem?


Regards,

Bart



void MyPrintf(char *fmt, ...)
{
char cBuffer[256];

va_list argptr;
int cnt;

va_start(argptr, fmt);
cnt = vsprintf(cBuffer, fmt, argptr);
va_end(argptr);

ShowMessage(cBuffer);
}
//---------------------------------------------------------------------------
int checkError (SQLRETURN rc, SQLSMALLINT handleType, SQLHANDLE handle, char
*errmsg)
{
SQLRETURN retcode = SQL_SUCCESS;
SQLSMALLINT errNum = 1;
SQLCHAR sqlState[6];
SQLINTEGER nativeError;
SQLCHAR errMsg[ERRMSG_LEN];
SQLSMALLINT textLengthPtr;
if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
{
while (retcode != SQL_NO_DATA)
{
retcode = SQLGetDiagRec (handleType, handle, errNum, sqlState,
&nativeError, errMsg, ERRMSG_LEN,
&textLengthPtr);
if (retcode == SQL_INVALID_HANDLE)
{
MyPrintf("checkError function was called with an invalid
handle!!\n");
return 1;
}
if ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO))
MyPrintf("ERROR: %d: %s : %s \n", (int) nativeError, (char
*)sqlState, errMsg);
errNum++;
}
MyPrintf("%s\n", errmsg);
return 1; /* all errors on this handle have been reported */
}
else
return 0; /* no errors to report */
}

The Code ......


void __fastcall TForm1::Button3Click(TObject *Sender)
{
int iC=0;
int iS=0;
SQLHDBC hdbc;
SQLHENV henv;
SQLHSTMT hstmt;

/* Miscellaneous variables */
UCHAR dsn[20]; /*name of the DSN used for connecting to the database*/
SQLRETURN rc = 0;

int in;
char* selectStmt = "SELECT data from grib_forecast_blob";
long mode = LO_RDONLY;
long lo_size;
long cbMode = 0, cbLoSize = 0;

strcpy (dsn, defDsn);


/* Allocate the Environment handle */
rc = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (rc != SQL_SUCCESS)
{
MyPrintf ("Environment Handle Allocation failed\nExiting!!\n");
return;
}

/* Set the ODBC version to 3.5 */
rc = SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3,
0);
if (checkError (rc, SQL_HANDLE_ENV, henv, "Error in Step 1 --
SQLSetEnvAttr failed\nExiting!!\n"))
return;


/* Allocate the connection handle */
rc = SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc);
if (checkError (rc, SQL_HANDLE_ENV, henv, "Error in Step 1 -- Connection
Handle Allocation failed\nExiting!!\n"))
return;

/* Establish the database connection */
rc = SQLConnect (hdbc, dsn, SQL_NTS, "", SQL_NTS, "", SQL_NTS);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 1 -- SQLConnect
failed\nExiting!!"))
return;

/* Allocate the statement handle */
rc = SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hstmt );
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 1 -- Statement
Handle Allocation failed\nExiting!!"))
return;

MyPrintf ("STEP 1 done...connected to database\n");


rc = SQLExecDirect (hstmt, selectStmt, SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLExecDirect failed\n"))
bStop=false;


while (!bStop)
{
rc = SQLFetch(hstmt);

if (rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO)
checkError(rc, SQL_HANDLE_STMT, hstmt,"Error from SQLFetch");

if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
{
char Buffer[100000];
long cbBlob;
SQLGetData(hstmt, 1, SQL_C_BINARY, Buffer, 100000, &cbBlob);
iC++;
iS += cbBlob;
Label1->Caption=IntToStr(iC);
Label2->Caption=IntToStr(iS);
Application->ProcessMessages();
}
// bStop=true;
}


/* Close the statement handle */
SQLFreeStmt (hstmt, SQL_CLOSE);

/* Free the statement handle */
SQLFreeHandle (SQL_HANDLE_STMT, hstmt);

/* Disconnect from the data source */
SQLDisconnect (hdbc);

/* Free the environment handle and the database connection handle */
SQLFreeHandle (SQL_HANDLE_DBC, hdbc);
SQLFreeHandle (SQL_HANDLE_ENV, henv);


}



Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #4 (permalink)  
Old 04-20-2008, 08:13 AM
Jonathan Leffler
 
Posts: n/a
Default Re: Memory Leak in getting blob's

Bart Huls wrote:

> Hi Jonathan,
>
> Ok here it goes....
> I tried it several ways lowlevel:
> This program produces in the loop a memory leak.It "leaks" by the blob size.
> Maybe I'm doing something wrong (and also Borland/ODBCExpress etc...) but I
> doubt this.
> Can you provide me some code which indicates that the retrieving of a blob
> is not an driver problem?


No - I don't program in ODBC.

I poked around, and eventually found the Informix-CLI 2.5 manual on
the IBM web site which contains some description of the various ODBC
function calls -- the later CSDK manuals do not go through each of the
separate functions in any detail.

Given what I found, I cannot see any immediate issue with the code you
present. I don't know whether there is some function call missing in
the sequence you use (I still don't program in ODBC). I do note that
you do not check the return value from SQLGetData() -- you should at
least do that. I'm still not convinced it would justify leaking
memory, but head off trouble before you get someone else throwing that
at you.

You didn't actually include the schema of the grib_forecast_blob
table, so I don't know whether you're dealing with a BYTE (or TEXT)
blob or a BLOB (or CLOB) blob. I'm not convinced it makes much
difference.

So, you've probably got something close to a test case - this isn't a
free-standing main() program, and there are a few other minor quibbles
of a similar nature. So, time to go to IBM/Informix Tech Support.

> void MyPrintf(char *fmt, ...)
> {
> char cBuffer[256];
>
> va_list argptr;
> int cnt;
>
> va_start(argptr, fmt);
> cnt = vsprintf(cBuffer, fmt, argptr);
> va_end(argptr);
>
> ShowMessage(cBuffer);
> }
> //---------------------------------------------------------------------------
> int checkError (SQLRETURN rc, SQLSMALLINT handleType, SQLHANDLE handle, char
> *errmsg)
> {
> SQLRETURN retcode = SQL_SUCCESS;
> SQLSMALLINT errNum = 1;
> SQLCHAR sqlState[6];
> SQLINTEGER nativeError;
> SQLCHAR errMsg[ERRMSG_LEN];
> SQLSMALLINT textLengthPtr;
> if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
> {
> while (retcode != SQL_NO_DATA)
> {
> retcode = SQLGetDiagRec (handleType, handle, errNum, sqlState,
> &nativeError, errMsg, ERRMSG_LEN,
> &textLengthPtr);
> if (retcode == SQL_INVALID_HANDLE)
> {
> MyPrintf("checkError function was called with an invalid
> handle!!\n");
> return 1;
> }
> if ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO))
> MyPrintf("ERROR: %d: %s : %s \n", (int) nativeError, (char
> *)sqlState, errMsg);
> errNum++;
> }
> MyPrintf("%s\n", errmsg);
> return 1; /* all errors on this handle have been reported */
> }
> else
> return 0; /* no errors to report */
> }
>
> The Code ......
>
>
> void __fastcall TForm1::Button3Click(TObject *Sender)
> {
> int iC=0;
> int iS=0;
> SQLHDBC hdbc;
> SQLHENV henv;
> SQLHSTMT hstmt;
>
> /* Miscellaneous variables */
> UCHAR dsn[20]; /*name of the DSN used for connecting to the database*/
> SQLRETURN rc = 0;
>
> int in;
> char* selectStmt = "SELECT data from grib_forecast_blob";
> long mode = LO_RDONLY;
> long lo_size;
> long cbMode = 0, cbLoSize = 0;
>
> strcpy (dsn, defDsn);
>
>
> /* Allocate the Environment handle */
> rc = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
> if (rc != SQL_SUCCESS)
> {
> MyPrintf ("Environment Handle Allocation failed\nExiting!!\n");
> return;
> }
>
> /* Set the ODBC version to 3.5 */
> rc = SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3,
> 0);
> if (checkError (rc, SQL_HANDLE_ENV, henv, "Error in Step 1 --
> SQLSetEnvAttr failed\nExiting!!\n"))
> return;
>
>
> /* Allocate the connection handle */
> rc = SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc);
> if (checkError (rc, SQL_HANDLE_ENV, henv, "Error in Step 1 -- Connection
> Handle Allocation failed\nExiting!!\n"))
> return;
>
> /* Establish the database connection */
> rc = SQLConnect (hdbc, dsn, SQL_NTS, "", SQL_NTS, "", SQL_NTS);
> if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 1 -- SQLConnect
> failed\nExiting!!"))
> return;
>
> /* Allocate the statement handle */
> rc = SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hstmt );
> if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 1 -- Statement
> Handle Allocation failed\nExiting!!"))
> return;
>
> MyPrintf ("STEP 1 done...connected to database\n");
>
>
> rc = SQLExecDirect (hstmt, selectStmt, SQL_NTS);
> if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
> SQLExecDirect failed\n"))
> bStop=false;
>
>
> while (!bStop)
> {
> rc = SQLFetch(hstmt);
>
> if (rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO)
> checkError(rc, SQL_HANDLE_STMT, hstmt,"Error from SQLFetch");
>
> if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
> {
> char Buffer[100000];
> long cbBlob;
> SQLGetData(hstmt, 1, SQL_C_BINARY, Buffer, 100000, &cbBlob);
> iC++;
> iS += cbBlob;
> Label1->Caption=IntToStr(iC);
> Label2->Caption=IntToStr(iS);
> Application->ProcessMessages();
> }
> // bStop=true;
> }
>
>
> /* Close the statement handle */
> SQLFreeStmt (hstmt, SQL_CLOSE);
>
> /* Free the statement handle */
> SQLFreeHandle (SQL_HANDLE_STMT, hstmt);
>
> /* Disconnect from the data source */
> SQLDisconnect (hdbc);
>
> /* Free the environment handle and the database connection handle */
> SQLFreeHandle (SQL_HANDLE_DBC, hdbc);
> SQLFreeHandle (SQL_HANDLE_ENV, henv);
> }




--
Jonathan Leffler #include <disclaimer.h>
Email: jleffler@earthlink.net, jleffler@us.ibm.com
Guardian of DBD::Informix v2003.04 -- http://dbi.perl.org/
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 09:35 AM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com