본문 바로가기

ProC

[PRO*C] 멀티 쓰레드 프로그램을 만들어서 돌리구 있씁니다.

Dynamic SQL Method 4 샘플 소스를 가져와서

멀티 쓰레드 프로그램을 만들어서 돌리구 있씁니다....

실행은 잘되는데...메모리가 계속 증가합니다...

커서 CLOSE 도 점검했고...프로그램 자체의 메모리 누수도 체크해 봤지만....

도저히 못잡겠습니다...

원본 소스를 올립니다...

오라클 버젼은... Oracle9i Release 9.2.0.1.0 - 64bit Production 입니다...

원래 오라클 버그가 있나요???

아니면...Dynamic SQL 을 쓸때...메모리가 증가 되는게 정상인가요???

고수님들 답변 부탁드립니다...

<makefile>

===================================================================================

#include $(ORACLE_HOME)/precomp/lib/env_precomp.mk

#
# ORACLE EBVIRONMENT FOR PROC-C,C++
#
ORA_DEFS = define=OLD_CUG PARSE=FULL ireclen=255 maxliteral=1024 CODE=ANSI_C THREADS=YES #HOLD_CURSOR=NO RELEASE_CURSOR=YES
ORA_INC = include=. include=../../dbinc include=../hdr include=$(OMNI_HOME)/include include=$(ORACLE_HOME)/precomp/public
ORA_LIBS = -L$(ORACLE_HOME)/lib
ORA_CFLAGS = MODE=ORACLE $(ORA_DEFS) $(ORA_INC) CLOSE_ON_COMMIT=YES

#
# MAKEFILE (BODY)
#
OUT = libmydb.a

CC = gcc
PROC = $(ORACLE_HOME)/bin/proc

INC = -I../../dbinc -I$(ORACLE_HOME)/precomp/public
LIB = -L/oracle/lib -L. -L/usr/lib $(ORA_LIBS)
LIBDIR = $(LIBDIR64)
COPTS =
LOPTS = /opt/stiSOP/misalign.o
CFLAGS = $(CLFAGS) -g -z mcpu=v9 -m64 $(INC) -D_REENTRANT -DSS_64BIT_SERVER -DBIT64 -DMACHINE64 -DPRECOMP
LFLAGS = $(LIB) -lm -lpthread -lmydb -lclntsh -lsocket -lnsl $(LOPT)

SRC = mydb.pc
ESQLC = $(SRC:.pc=.c)
OBJ = $(SRC:.pc=.o)

#
# SUFFIX RULE
#
.SUFFIXES : .pc .c .o

.pc.o : $(SRC)
$(PROC) iname=$*.pc $(ORA_CFLAGS)
$(CC) -c $(CFLAGS) $*.c $(LFLAGS) $(INC)
$(C2O_64)


.pc.c : $(SRC)
$(PROC) iname=$*.pc $(ORA_CFLAGS)

.c.o : $(CFILES)
$(CC) -c $(CFLAGS) $*.c
$(C2O_64)

#
# COMMAND
#

all : $(OUT)

$(OUT) : $(ESQLC) $(OBJ)
@echo Building $@
@rm -f $@
@ar -rcsv $@ $(OBJ)

@ranlib $@

install :
@echo Copy libagent_dbapi.a to ../lib
cp *.a ../


clean :
rm -f $(OBJ) $(ESQLC) core $(OUT) test_mydb test_mydb.o *~

test : test_mydb.o
$(CC) -o test_mydb test_mydb.o $(LFLAGS)


<소스>

===================================================================================

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include <sqlda.h>
#include <sqlcpr.h>

#include "mydb.h"

typedef struct db_sess {
struct db_sess *next;
struct db_sess **prev;
int sid; /* DB session id */
sql_context ctx; /* context */
SQLDA *sp; /* sqlda.select */
SQLDA *bp; /* sqlda.bind */
bind_t bind[MAXBIND]; /* bind list */
} db_t;


/*
* HASH Function
*/

#define db_hash_size 1
#define MAX_VNAME_LEN 30

db_t *dbhash[db_hash_size] = { NULL, };
uint32_t db_sessfn(int sid) { return (db_hash_size - 1) & sid; }


EXEC SQL INCLUDE sqlda;
EXEC SQL INCLUDE sqlca;

EXEC SQL BEGIN DECLARE SECTION;
char qry[2048];
EXEC SQL VAR qry IS STRING(2048);
EXEC SQL END DECLARE SECTION;


void db_hash(db_t *p)
{
db_t **pp = &dbhash[db_sessfn(p->sid)];
if((p->next = *pp))
p->next->prev = &p->next;
p->prev = pp;
*pp = p;
}

void db_unhash(db_t *p)
{
if(p->prev) {
if((*(p->prev) = p->next))
p->next->prev = p->prev;
p->next = NULL;
p->prev = NULL;
}
}
db_t* db_find(int sid)
{
db_t *p;

for(p=dbhash[db_sessfn(sid)];p;p=p->next) {
if(p->sid!=sid) continue;
return p;
}
return NULL;
}

db_t* db_add(int sid)
{
db_t *p;
if(p=db_find(sid)) return NULL;
p = (db_t*)malloc(sizeof(db_t));
if(p) {
p->next = NULL;
p->prev = NULL;
p->sid = sid;
db_hash(p);
}
return p;
}

void db_del(int sid)
{
db_t *p;
if(!(p=db_find(sid))) {
printf ( "sid not found ( sid = %d ) \n", sid);
return; /* not found */
}
db_unhash(p);
free(p);
}


#define MAXVLEN 30
#define MAXILEN 30

void sql_error()
{
/* ORACLE error handler */
printf ("\n\n");
printf ("######################################\n");
printf ("ORACLE ERROR: %70s\n",sqlca.sqlerrm.sqlerrmc);
printf ("######################################\n");
printf ("\n\n");
}

int db_conn()
{
db_t *p;

char szUser[16];
char szPass[16];
char szDBHost[16];

int sid=1,i;

strcpy(szUser, USER);
strcpy(szPass, PASS);
strcpy(szDBHost, DBHOST);

EXEC SQL ENABLE THREADS;

if(!dbhash[0]) {
#if 1
EXEC SQL WHENEVER SQLERROR DO sql_error();
#endif
}
while( !(p=db_add(sid)) ) sid+=1;
EXEC SQL CONTEXT ALLOCATE :p->ctx;
EXEC SQL CONTEXT USE :p->ctx;

EXEC SQL CONNECT :szUser IDENTIFIED BY :szPass;

if( !(p->sp=SQLSQLDAAlloc(p->ctx,MAXBIND,MAXVLEN,MAXILEN)) ) return -1;
if( !(p->bp=SQLSQLDAAlloc(p->ctx,MAXBIND,MAXVLEN,MAXILEN)) ) return -1;

p->sp->N = MAXBIND;
for (i = 0; i < MAXBIND; i++) {
p->sp->I[i] = (short*)malloc(sizeof(short));
p->bp->I[i] = (short*)malloc(sizeof(short));
p->sp->V[i] = (char*)malloc(1);
p->bp->V[i] = (char*)malloc(1);
}
return sid;
}

int db_bind(uint32_t sid,int col,int type,int len,char *s)
{
db_t *p;
if( !(p=db_find(sid)) )return -1;
EXEC SQL CONTEXT USE :p->ctx;

p->bind[col].type = type;
p->bind[col].len = len;
p->bind[col].p = s;
return 1;
}

int db_select(uint32_t sid,char *stm)
{
db_t *p;
SQLDA *bp=NULL;

memcpy(qry,stm,2048);

if( !(p=db_find(sid)) )return -1;

EXEC SQL CONTEXT USE :p->ctx;

p->bp->F = 0;
EXEC SQL PREPARE S FROM :qry;
EXEC SQL DECLARE C CURSOR FOR S;

set_bind(p);

bp = p->bp;
EXEC SQL OPEN C USING DESCRIPTOR bp;

do_select(p,qry);

return 1;
}

int db_exec(uint32_t sid,char *stm)
{
db_t *p;

if( !(p=db_find(sid)) )return -1;
EXEC SQL CONTEXT USE :p->ctx;

db_select(sid, stm);

#if 1
EXEC SQL CLOSE C;
#endif

return 0;
}


int db_commit(uint32_t sid)
{
db_t *p;
SQLDA *sp;

if( !(p=db_find(sid)) )return -1;
EXEC SQL CONTEXT USE :p->ctx;

EXEC SQL COMMIT WORK;
EXEC SQL CACHE FREE ALL;
}

int db_free(uint32_t sid)
{
db_t *p;

if( !(p=db_find(sid)) )return -1;
EXEC SQL CONTEXT USE :p->ctx;

EXEC SQL COMMIT WORK;
return 1;
}

int db_disc(uint32_t sid)
{
int i;
db_t *p;

if( !(p=db_find(sid)) )return -1;
EXEC SQL CONTEXT USE :p->ctx;

for (i = 0; i < MAXBIND; i++) {
free(p->sp->I[i]) ;
free(p->bp->I[i]) ;
if ( p->sp->V[i] != (char*)0 )
free(p->sp->V[i]);
if ( p->bp->V[i] != (char*)0 )
free(p->bp->V[i]);
}

SQLSQLDAFree(p->ctx,p->sp);
SQLSQLDAFree(p->ctx,p->bp);

EXEC SQL CACHE FREE ALL;
EXEC SQL COMMIT WORK RELEASE;
EXEC SQL CONTEXT FREE :p->ctx;
#if 0
EXEC SQL ROLLBACK WORK RELEASE;
#endif

db_del(sid);
return 0;
}

int set_bind(db_t *p)
{
int i, n;
SQLDA *bp;

if(!p) return;
EXEC SQL CONTEXT USE :p->ctx;

bp = p->bp;
bp->N = MAXBIND;

EXEC SQL DESCRIBE BIND VARIABLES FOR S INTO bp;

if(bp->F<0) {
printf("\nToo many variable\n");
return 0;
}
bp->N = bp->F;

return 0;
}

int do_select(db_t *p, char *stm)
{
int i, null_ok, precision, scale;
char title[MAX_VNAME_LEN];
SQLDA *sp;

memcpy(qry,stm,2048);

if(!p) return -1;
EXEC SQL CONTEXT USE :p->ctx;


if ((strncmp(qry, "SELECT", 6) != 0) &&
(strncmp(qry, "select", 6) != 0))
{
p->sp->F = 0;
return;
}

/* If the SQL statement is a SELECT, describe the
select-list items. The DESCRIBE function returns
their names, datatypes, lengths (including precision
and scale), and NULL/NOT NULL statuses. */

p->sp->N = MAXBIND;
sp = p->sp;

EXEC SQL DESCRIBE SELECT LIST FOR S INTO sp;

/* If F is negative, there were more select-list
items than originally allocated by SQLSQLDAAlloc(). */
if (p->sp->F < 0)
{
printf ("\nToo many select-list items (%d), maximum is %d\n",
-(p->sp->F), MAXBIND);
return;
}

/* Set the maximum number of array elements in the
descriptor to the number found. */
p->sp->N = p->sp->F;


for (i = 0; i < p->sp->F; i++)
{
/* Turn off high-order bit of datatype (in this example,
it does not matter if the column is NOT NULL). */
SQLColumnNullCheck (p->ctx,(unsigned short *)&(p->sp->T[i]),
(unsigned short *)&(p->sp->T[i]), &null_ok);

switch (p->sp->T[i])
{
case 1 : /* CHAR datatype: no change in length
needed, except possibly for TO_CHAR
conversions (not handled here). */
break;
case 2 : /* NUMBER datatype: use SQLNumberPrecV6() to
extract precision and scale. */
SQLNumberPrecV6(p->ctx,(uint32_t *)&(p->sp->L[i]),&precision,&scale);
/* Allow for maximum size of NUMBER. */
if (precision == 0) precision = 40;
/* Also allow for decimal point and
possible sign. */
/* convert NUMBER datatype to FLOAT if scale > 0,
INT otherwise. */
if (scale > 0)
p->sp->L[i] = sizeof(float);
else
p->sp->L[i] = sizeof(int);
break;

case 8 : /* LONG datatype */
p->sp->L[i] = 240;
break;

case 11 : /* ROWID datatype */
p->sp->L[i] = 18;
break;

case 12 : /* DATE datatype */
p->sp->L[i] = 9;
break;

case 23 : /* RAW datatype */
break;

case 24 : /* LONG RAW datatype */
p->sp->L[i] = 240;
break;
}
/* Allocate space for the select-list data values.
SQLSQLDAAlloc() reserves a pointer location for
V[i] but does not allocate the full space for
the pointer. */

if (p->sp->T[i] != 2)
p->sp->V[i] = (char *) realloc(p->sp->V[i],
p->sp->L[i] + 1);
else
p->sp->V[i] = (char *) realloc(p->sp->V[i],
p->sp->L[i]);

}

return 0;
}

int db_fetch(uint32_t sid)
{
db_t *p;
int i;
SQLDA *sp;

if( !(p=db_find(sid)) )return -1;
EXEC SQL CONTEXT USE :p->ctx;

EXEC SQL WHENEVER NOT FOUND GOTO ENDLOOP;
sp = p->sp;

EXEC SQL FETCH C USING DESCRIPTOR sp;

for(i=0;i<p->sp->F;i++)
{
if( *sp->I[i] >= 0) {
if (p->bind[i].p == NULL) continue;
switch(p->bind[i].type) {
case DB_TYPE_STRING :
strncpy(p->bind[i].p,p->sp->V[i],p->bind[i].len);
break;
case DB_TYPE_U32 :
*(uint32_t*)p->bind[i].p = *(int*)(p->sp->V[i]);
break;
case DB_TYPE_U16 :
*(uint16_t*)p->bind[i].p = (uint16_t)*(int*)(p->sp->V[i]);
break;
case DB_TYPE_U8 :
*(uchar_t*)p->bind[i].p = (uchar_t)*(int*)(p->sp->V[i]);
break;
case DB_TYPE_IPADDR :
*(uint32_t*)p->bind[i].p = inet_addr(p->sp->V[i]);
break;
}
}
}

#if 1
EXEC SQL CLOSE C;
#endif
return i; /* update Nam.cw 2005/04/18 */

ENDLOOP:
#if 1
EXEC SQL CLOSE C;
#endif
return 0;
}
=================================================================

관련 있는거 같아 올려봅니다.

참고하세요

Bug 2717317Client memory leak from EXEC SQL CONTEXT ALLOCATE / FREE

This note gives a brief overview of bug 2717317.

Affects:

Product (Component)

Precompilers (Pro*C)

Range of versions believed to be affected

Versions >= 9.2 but < 10G

Versions confirmed as being affected

  • 9.2.0.1
  • 9.2.0.2

Platforms affected

Generic (all / most platforms affected)


It is believed to be a regression in default behaviour thus:

· Regression introduced in 9.2.0.1

Fixed:

This issue is fixed in

  • 9.2.0.3 (Server Patch Set)
  • 10G Production Base Release

Symptoms:

Related To:

  • Pro* Precompiler

Description

This problem is introduced in 9.2

Client memory leak possible from EXEC SQL CONTEXT ALLOCATE / FREE

'ProC' 카테고리의 다른 글

Pro*C 개요  (0) 2011.10.16
Pro*C의 기초  (0) 2011.10.16
[ORACLE] pro*c makefile 만들기  (0) 2011.10.16
Make file for Pro*c  (0) 2011.10.16
[pro*c] 오라클DB 에 이미지 넣기 예제  (0) 2011.10.16