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 |
|
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 |
|
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 |