| Oracle FAQ | Your Portal to the Oracle Knowledge Grid | |
Home -> Community -> Usenet -> c.d.o.tools -> Re: OCIParamGet memory leak
Sorry, my last reply got truncated for some reason.
Yes, this is just some example code which highlights the memory leak. I modified the cdemo81.c example program that ships with Oracle and added this bogus loop. Here is the real code. I added the part indicated by the "/* new code */" comment.
db
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <oci.h>
static text *username = (text *) "SCOTT"; static text *password = (text *) "TIGER";
/* Define SQL statements to be used in program. */
static text *insert = (text *)"INSERT INTO emp(empno, ename, job, sal,
deptno)\
VALUES (:empno, :ename, :job, :sal, :deptno)";
static text *seldept = (text *)"SELECT dname FROM dept WHERE deptno =
:1";
static text *maxemp = (text *)"SELECT NVL(MAX(empno), 0) FROM emp";
static text *selemp = (text *)"SELECT ename job FROM emp";
static OCIEnv *envhp;
static OCIError *errhp;
static void checkerr(OCIError *errhp, sword status );
static void cleanup(/*_ void _*/);
static void myfflush(/*_ void _*/);
static sword status;
int main(int argc, char** argv)
{
sword empno, sal, deptno;
sword len, len2, rv, dsize, dsize2;
sb4 enamelen = 10; sb4 joblen = 9; sb4 deptlen = 14; sb2 sal_ind, job_ind; sb2 db_type, db2_type; sb1 name_buf[20], name2_buf[20]; text *cp, *ename, *job, *dept; sb2 ind[2]; /* indicator */ ub2 alen[2]; /* actual length */ ub2 rlen[2]; /* returnlength */
OCIDescribe *dschndl1 = (OCIDescribe *) 0,
*dschndl2 = (OCIDescribe *) 0,
*dschndl3 = (OCIDescribe *) 0;
OCISession *authp = (OCISession *) 0;
OCIServer *srvhp;
OCISvcCtx *svchp;
OCIStmt *inserthp,
*stmthp,
*stmthp1,
*sp,
*sp1;
OCIBind *bnd1p = (OCIBind *) 0; /* the first bind handle
*/
OCIBind *bnd2p = (OCIBind *) 0; /* the second bind handle
*/
OCIBind *bnd3p = (OCIBind *) 0; /* the third bind handle
*/
OCIBind *bnd4p = (OCIBind *) 0; /* the fourth bind handle
*/
OCIBind *bnd5p = (OCIBind *) 0; /* the fifth bind handle
*/
OCIBind *bnd6p = (OCIBind *) 0; /* the sixth bind handle
*/
(void) OCIInitialize((ub4) OCI_DEFAULT, (dvoid *)0,
(dvoid * (*)(dvoid *, size_t)) 0,
(dvoid * (*)(dvoid *, dvoid *, size_t))0,
(void (*)(dvoid *, dvoid *)) 0 );
(void) OCIEnvInit( (OCIEnv **) &envhp, OCI_DEFAULT, (size_t) 0,
(dvoid **) 0 );
(void) OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &errhp, OCI_HTYPE_ERROR,
(size_t) 0, (dvoid **) 0);
/* server contexts */
(void) OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &srvhp,
OCI_HTYPE_SERVER,
(size_t) 0, (dvoid **) 0);
(void) OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &svchp, OCI_HTYPE_SVCCTX,
(size_t) 0, (dvoid **) 0);
(void) OCIServerAttach( srvhp, errhp, (text *)"trol", strlen("trol"), 0);
/* set attribute server context in the service context */ (void) OCIAttrSet( (dvoid *) svchp, OCI_HTYPE_SVCCTX, (dvoid *)srvhp,
(ub4) 0, OCI_ATTR_SERVER, (OCIError *) errhp);
(void) OCIHandleAlloc((dvoid *) envhp, (dvoid **)&authp,
(ub4) OCI_HTYPE_SESSION, (size_t) 0, (dvoid **)
0);
(void) OCIAttrSet((dvoid *) authp, (ub4) OCI_HTYPE_SESSION,
(dvoid *) username, (ub4) strlen((char *)username),
(ub4) OCI_ATTR_USERNAME, errhp);
(void) OCIAttrSet((dvoid *) authp, (ub4) OCI_HTYPE_SESSION,
(dvoid *) password, (ub4) strlen((char *)password),
(ub4) OCI_ATTR_PASSWORD, errhp);
checkerr(errhp, OCISessionBegin ( svchp, errhp, authp, OCI_CRED_RDBMS,
(ub4) OCI_DEFAULT));
(void) OCIAttrSet((dvoid *) svchp, (ub4) OCI_HTYPE_SVCCTX,
(dvoid *) authp, (ub4) 0,
(ub4) OCI_ATTR_SESSION, errhp);
checkerr(errhp, OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &stmthp,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
checkerr(errhp, OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &stmthp1,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
/* Retrieve the current maximum employee number. */
checkerr(errhp, OCIStmtPrepare(stmthp, errhp, maxemp,
(ub4) strlen((char *) maxemp),
(ub4) OCI_NTV_SYNTAX, (ub4)
OCI_DEFAULT));
/* bind the input variable */
(sword) sizeof(sword), SQLT_INT, (dvoid *) 0, (ub2
*)0,
(ub2 *)0, OCI_DEFAULT));
/* execute and fetch */
if (status = OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,
(CONST OCISnapshot *) NULL, (OCISnapshot *) NULL,
OCI_DEFAULT))
{
if (status == OCI_NO_DATA)
empno = 10;
else
{
checkerr(errhp, status);
cleanup();
return OCI_ERROR;
checkerr(errhp, OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &sp,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
checkerr(errhp, OCIStmtPrepare(sp, errhp, selemp,
(ub4) strlen((char *) selemp),
(ub4) OCI_NTV_SYNTAX, (ub4)
OCI_DEFAULT));
ename = (text*)new char[255];
(sword) 255, SQLT_CHR, (dvoid *) 0, (ub2 *)0,
(ub2 *)0, OCI_DEFAULT));
if ((status = OCIStmtExecute(svchp, sp, errhp, (ub4) 1, (ub4) 0,
(CONST OCISnapshot *) NULL, (OCISnapshot *) NULL,
OCI_DESCRIBE_ONLY) )
&& status != 1)
{
checkerr(errhp, status);
cleanup();
return OCI_ERROR;
}
/* new code */
OCIParam *mypard=0;
ub4 counter;
ub2 dtype;
text *col_name;
ub4 col_name_len;
sb4 parm_status;
counter = 1;
parm_status = OCIParamGet(sp, OCI_HTYPE_STMT, errhp, reinterpret_cast<void**>(&mypard),
(ub4) counter);
/* Loop only if a descriptor was successfully retrieved for
current position, starting at 1 */ while (parm_status==OCI_SUCCESS) {
/* Retrieve the data type attribute */
checkerr(errhp, OCIAttrGet((dvoid*) mypard, (ub4) OCI_DTYPE_PARAM,
(dvoid*) &dtype,(ub4 *) 0, (ub4) OCI_ATTR_DATA_TYPE,
(OCIError *) errhp ));
/* Retrieve the column name attribute */
checkerr(errhp, OCIAttrGet((dvoid*) mypard, (ub4)
OCI_DTYPE_PARAM,
(dvoid**) &col_name,(ub4 *) &col_name_len, (ub4) OCI_ATTR_NAME,
(OCIError *) errhp ));
printf("column=%s datatype=%d\n\n", col_name, dtype);
fflush(stdout);
/* increment counter and get next descriptor, if there is one */
counter++;
parm_status = OCIParamGet(sp, OCI_HTYPE_STMT, errhp,
(dvoid**)&mypard,
(ub4) counter);
/*
checkerr(errhp, OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &inserthp,
OCI_HTYPE_STMT, (size_t) enamelen + 2 + joblen + 2,
(dvoid **) &ename));
checkerr(errhp, OCIStmtPrepare(stmthp, errhp, insert,
(ub4) strlen((char *) insert),
(ub4) OCI_NTV_SYNTAX, (ub4)
OCI_DEFAULT));
checkerr(errhp, OCIStmtPrepare(stmthp1, errhp, seldept,
(ub4) strlen((char *) seldept),
(ub4) OCI_NTV_SYNTAX, (ub4)
OCI_DEFAULT));
/* Bind the placeholders in the INSERT statement. */
if ((status = OCIBindByName(stmthp, &bnd1p, errhp, (text *) ":ENAME",
-1, (dvoid *) ename,
enamelen+1, SQLT_STR, (dvoid *) 0,
(ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)) ||
(status = OCIBindByName(stmthp, &bnd2p, errhp, (text *) ":JOB",
-1, (dvoid *) job,
joblen+1, SQLT_STR, (dvoid *) &job_ind,
(ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)) ||
(status = OCIBindByName(stmthp, &bnd3p, errhp, (text *) ":SAL",
-1, (dvoid *) &sal,
(sword) sizeof(sal), SQLT_INT, (dvoid *) &sal_ind,
(ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)) ||
(status = OCIBindByName(stmthp, &bnd4p, errhp, (text *) ":DEPTNO",
-1, (dvoid *) &deptno,
(sword) sizeof(deptno), SQLT_INT, (dvoid *) 0,
(ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)) ||
(status = OCIBindByName(stmthp, &bnd5p, errhp, (text *) ":EMPNO",
-1, (dvoid *) &empno,
(sword) sizeof(empno), SQLT_INT, (dvoid *) 0,
(ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)))
{
/* Bind the placeholder in the "seldept" statement. */ if (status = OCIBindByPos(stmthp1, &bnd6p, errhp, 1,
(dvoid *) &deptno, (sword) sizeof(deptno),SQLT_INT,
(dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0,
OCI_DEFAULT))
/* Allocate the dept buffer now that you have length. */
/* the deptlen should eventually get from dschndl3. */
deptlen = 14;
dept = (text *) malloc((size_t) deptlen + 1);
/* Define the output variable for the select-list. */
if (status = OCIDefineByPos(stmthp1, &defnp, errhp, 1,
(dvoid *) dept, deptlen+1, SQLT_STR,
(dvoid *) 0, (ub2 *) 0, (ub2 *) 0,
OCI_DEFAULT))
for (;;)
{
/* Prompt for employee name. Break on no name. */
printf("\nEnter employee name (or CR to EXIT): ");
fgets((char *) ename, (int) enamelen+1, stdin);
cp = (text *) strchr((char *) ename, '\n');
if (cp == ename)
{
printf("Exiting... ");
cleanup();
return OCI_SUCCESS;
printf("Employee name may be truncated.\n");
myfflush();
job_ind = -1; /* make it NULL in table */
printf("Job is NULL.\n");/* using indicator variable */
}
printf("Job description may be truncated.\n");
myfflush();
printf("Enter employee salary: ");
scanf("%d", &sal);
myfflush();
sal_ind = (sal <= 0) ? -2 : 0; /* set indicator variable */
/*
* Prompt for the employee's department number, and verify
* that the entered department number is valid
* by executing and fetching.
*/
printf("Enter employee dept: ");
scanf("%d", &deptno);
myfflush();
if ((status = OCIStmtExecute(svchp, stmthp1, errhp, (ub4) 1, (ub4)
0,
(CONST OCISnapshot *) NULL, (OCISnapshot *) NULL,
OCI_DEFAULT))
&& (status != OCI_NO_DATA))
{
checkerr(errhp, status);
cleanup();
return OCI_ERROR;
}
if (status == OCI_NO_DATA)
printf("The dept you entered doesn't exist.\n");
} while (status == OCI_NO_DATA);
/*
* Increment empno by 10, and execute the INSERT
* statement. If the return code is 1 (duplicate
* value in index), then generate the next
* employee number.
*/
empno += 10;
if ((status = OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4)
0,
(CONST OCISnapshot *) NULL, (OCISnapshot *) NULL,
OCI_DEFAULT))
&& status != 1)
{
checkerr(errhp, status);
cleanup();
return OCI_ERROR;
}
while (status == 1)
{
empno += 10;
if ((status = OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1,
(ub4) 0,
(CONST OCISnapshot *) NULL, (OCISnapshot *) NULL,
OCI_DEFAULT))
&& status != 1)
{
checkerr(errhp, status);
cleanup();
return OCI_ERROR;
}
} /* end for (;;) */
/* Commit the change. */
if (status = OCITransCommit(svchp, errhp, 0))
{
checkerr(errhp, status);
cleanup();
return OCI_ERROR;
}
printf("\n\n%s added to the %s department as employee number
%d\n",
ename, dept, empno);
void checkerr(OCIError* errhp, sword status)
{
text errbuf[512];
sb4 errcode = 0;
switch (status)
{
case OCI_SUCCESS:
break;
case OCI_SUCCESS_WITH_INFO:
(void) printf("Error - OCI_SUCCESS_WITH_INFO\n");
break;
case OCI_NEED_DATA:
(void) printf("Error - OCI_NEED_DATA\n");
break;
case OCI_NO_DATA:
(void) printf("Error - OCI_NODATA\n");
break;
case OCI_ERROR:
(void) OCIErrorGet((dvoid *)errhp, (ub4) 1, (text *) NULL, &errcode,
errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
(void) printf("Error - %.*s\n", 512, errbuf);
break;
/* * Exit program with an exit code. */
void myfflush()
{
eb1 buf[50];
fgets((char *) buf, 50, stdin);
}
/* end of file cdemo81.c */
In article <8t6e5l$lp$1_at_nnrp1.deja.com>, edwardmi1_at_my-deja.com wrote:
> Hi and see comments below:
>
> > Assuming I have created a statement and executed it, should the
> > following loop leak memory?
> >
> > OCIParam *mypard=0;
> > ub4 counter;
> > sb4 parm_status;
> >
> > counter = 1;
> >
> > for (int xx=0;xx<100000;++xx) {
> > parm_status = OCIParamGet(sp, OCI_HTYPE_STMT, errhp,
> > reinterpret_cast<void**>(&mypard),
> > (ub4) counter);
> > }
>
> Is it real for() loop or just for an example?
>
> Help me with the following things:
>
> D'you really have 100000 columns for your statement ???
> D'you really do not check return code of OCIParamGet() for
OCI_NO_DATA?
> (or 100000 is a result of the previous call of OCIAttrGet() with > OCI_ATTR_PARAM_COUNT ?) > And, last, what is the use to call OCIParamGet() 100000 times > with the same value of the last parameter - I mean "counter"? > > If this is a real code ... > If this is just for an example let me see your real code. > > > > > I leak a few MBs of memory with the above. I am using the OCIlibrary
> > provided with Oracle 8.1.6 for Linux. Can someone clue me in on why > > this is happening? > > > > Sent via Deja.com http://www.deja.com/ > > Before you buy. > > > > Sent via Deja.com http://www.deja.com/ > Before you buy. >
Sent via Deja.com http://www.deja.com/
Before you buy.
Received on Thu Oct 26 2000 - 13:36:31 CDT
![]() |
![]() |