Re: Memory leaks using Informix SE 5.0
Posted in 1995
There was a major change in the internals of how memory for cursors and statements was handled between the 4.1x and the 5.0x (and later) releases. With 5.00 and above, you should probably free both the cursor and the prepared statement. If you have Purify or an equivalent memory leak detector, then you be able to tell if it won't work because you'll start getting errors about freeing already freed memory. If you don't have something that can tell you reliably about such memory abuses, get a checking malloc() that will complain reliably if you abuse memory -- I have a paranoid malloc() which will spot double releases of the same chunk of memory. which is what I'm most concerned about. These should have been documented in the 5.0x manuals, but may not have been; and it was a subtle change and was not highlighted in any manual that I recall. There was simply a description of the changed behaviour. And I seem to remember running into some variations in behaviour when 5.00 first came out (early 1991), but those should have settled down by now with any version you are likely to be using. Watch out for DESCRIBE and it's memory allocation. Yours, Jonathan Leffler (johnl@informix.com) #include <disclaimer.h> }From: rflattin@ascus.com (Roger Flattin) }Date: 04 Dec 1995 16:44:17 GMT }X-Informix-List-Id: <list.8134> } }We encounter the following problem using Informix SE on several servers (Sun }SunOS 4.1.3, HP HP/UX 9.04) on the following program written in ESQL/C : } }/*****************************************************************/ }#include <stdio.h> } }EXEC SQL INCLUDE sqlca; }EXEC SQL INCLUDE sqlda; } }/* }** Handle SQL errors }*/ } }void my_handle_error() }{ } fprintf( stderr, "sqlcode=%d\\n", sqlca.sqlcode ); } exit( 1 ); }} } }/* }** Prepare, describe, declare a cursor for a select. }** You can put any select in the parameter. }** We you call several times this function, you loose some }** memory (about 1 Ko each time). }*/ } }void testinf( q_string ) }EXEC SQL BEGIN DECLARE SECTION; } char *q_string; }EXEC SQL END DECLARE SECTION; }{ } struct SQLDA *q_desc; } } EXEC SQL prepare sqlobj from $q_string; } if(sqlca.sqlcode<0) my_handle_error(); } } EXEC SQL describe sqlobj into q_desc; } if(sqlca.sqlcode<0) my_handle_error(); } } EXEC SQL declare sqlcurs cursor with hold for sqlobj; } if(sqlca.sqlcode<0) my_handle_error(); } } EXEC SQL open sqlcurs; } if(sqlca.sqlcode<0) my_handle_error(); } } EXEC SQL close sqlcurs; } if(sqlca.sqlcode<0) my_handle_error(); } } EXEC SQL free sqlobj; } if(sqlca.sqlcode<0) my_handle_error(); }} } }/* }** Here is the main function of our program. }** It calls 5 times the function that create the cursor for the select. }*/ } }main() }{ } int i; } } EXEC SQL database our_database; /* <- pur there the name of your database }*/ } } for( i = 0; i < 5; i++ ) } testinf( "select count(*) from adresses" ); } } exit( 0 ); }} }/*******************************************************************/ } }We declare, open and close a cursor on a select statment (any select shows }the problem). If we call the testinf() function, we got a memory leak of 64 }bytes. } }Il we call the testinf() function 5 times (the ESQL/C program supply with }this message executes the testinf() function 5 times) we obtains several }memory leaks : } } 1024 bytes (4 times) = 4096 total bytes. } _sqrealloc (iqutil.o) } _sqg_desc (iqreturn.o) } _sqr_desc (iqreturn.o) } _iqprepare (iqdynam.o) } _iqnprep (iqdynam.o) } testinf (testinf.o) } } 64 bytes (5 times) = 320 total bytes. } _sqrealloc (iqutil.o) } _iqnormdesc (iqdynam.o) } _iqdescribe (iqdynam.o) } testinf (testinf.o) } main (testinf.o) } start (usr_lib_crt0.o) } } 11 bytes (4 times) = 44 total bytes. } _sqrealloc (iqutil.o) } _sqg_desc (iqreturn.o) } _sqr_desc (iqreturn.o) } _iqprepare (iqdynam.o) } _iqnprep (iqdynam.o) } testinf (testinf.o) } } 10 bytes (4 times) = 40 total bytes. } _sqrealloc (iqutil.o) } _sqg_desc (iqreturn.o) } _sqr_desc (iqreturn.o) } _iqprepare (iqdynam.o) } _iqnprep (iqdynam.o) } testinf (testinf.o) } }It seems that the Informix functions that replace the different EXEC SQL }statment allocate the memory blocks they needs each times they are called }(that could be the reason why there are 4 memory leaks for each block size). } }The 64 bytes block seems to be the _SQCURSOR structure describe in sqlhdr.h }and returns by the _iqnprep() Informix internal function. The others memory }leaks could be some of the pointers contain in this structure. } }How can we do to avoid this problem. We don't know how to free the memory }blocks allocated by the underlying ESQL/C functions. } }Thanks in advance. } }Roger FLATTIN }CORNUT Informatique } }+------------------------------------+--------------------------+ }| Roger Flattin | Phone : (33) 77 93 57 46 | }| Cornut Informatique | Fax : (33) 77 92 51 39 | }| 24, rue de la Telematique - BP 702 | AppleLink : CORNUT.INF | }| 42950 St Etienne cedex 9 FRANCE | Compuserve: 100303,1061 | }| frederic_bouquet@ascus.com | | }+------------------------------------+--------------------------+