버클리DB를 사용해서 개발시에..
글쓴이: rokmn3309 / 작성시간: 수, 2004/11/17 - 1:16오후
테스트로 main()함수 안에서 cursor를 열어서 데이터 읽기했을때는 문제가 없었으나 함수로 빼서 cursor를 열어서 읽기를 시도 했을때에 DB_NEXT 옵션사용시 데이터가 없다거나, DB_SET 옵션사용시 메모리 할당을 할수 없다는 메세지가 나옵니다..
cursor생성시에는 에러나 오류등은 없었습니다. DB4-4.0.x,4.1에서 나타나는 현상은 동일했습니다.
main에서 하는거와 함수로 빼서 하는거랑 어떤 차이가 있는지 알수가 없군요.
아래는 대충적인 소스입니다.
다만 함수로 뺐을때에 다음과 같은 cursor를 사용안했을때에는 정상적으로 동작합니다.
ret = dbp->get(dbp, NULL, &key, &data,0); ret = dbp->put(dbp, NULL,&key, &data, DB_NOOVERWRITE); ret = dbp->del(dbp, NULL,&key,0);
DB *dbp; DBC *dbcp; DBT key, data; typedef struct imi_struct { char seq[32]; char name[64]; unsigned long age; unsigned int sex; char addr[128]; } StructDef; int open_database(char *dbname){ //DB 오픈 } int close_database(){ //DB 종료 } int execute_database(StructDef *dstr,char *dbname,int act){ int ret = 0; if(open_database(dbname)==0){ memset(&key, 0, sizeof(DBT)); memset(&data, 0, sizeof(DBT)); ret = dbp->cursor(dbp, NULL, &dbcp, 0); if (ret != 0) { printf("Create cursor failed : %s\n",db_strerror(ret)); goto err2; } data.data = dstr; data.size = sizeof(StructDef); data.flags = DB_DBT_USERMEM; while( (ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0 ){ printf("seq: %s", dstr->seq); printf("\tname: %s", dstr->name); printf("\tage: %d", dstr->age); printf("\tsex: %d", dstr->sex); printf("\taddr: %s\n", dstr->addr); } if (ret != DB_NOTFOUND) { printf("data is not exist\n"); } if (dbcp != NULL) dbcp->c_close(dbcp); if(close_database()!=0) goto err; } } return 0; err: (void)dbp->close(dbp, 0); return -1; err2: (void)dbcp->c_close(dbcp); goto err; } int main(int argc, char *argv[]){ StructDef mydata; memset(&mydata, 0, sizeof(StructDef)); if(execute_database(&mydata,"my_sample.db",5)==0){ printf("select all succeed\n"); } return 0; }
Forums:
답글..
함수에서 레코드를 불러오든 main()에서 불러오든 전혀 관계 없습니다.
더우기 전역변수로 선언 되었기어 더욱 그렇지요..
get()함수에서 레코드 불러오기가 안된다고 하셨는데..
"DB_NEXT", "DB_SET" 등은 c_get() 함수의 매개 변수 입니다.
c_get()함수의 매개변수로 DB_NEXT를 사용하여 while()문으로 반복을 하면 첫레코드부터 마지막 레코드 까지 순회합니다.
하지만 get()함수는 다른 용도로 사용을 합니다.
key값을 설정한후 해당레코드에 직접 접근을 하는 경우등으로 사용을 하지요..
자세한 사항은 버클리 API 레퍼런스를 참고 하세요..
m.m
m.m
위에서 처음에 글 쓸때에.. get(),put(),del()은 이상없이 되고..
커서를 사용할때 안된다고 했는데 .. 제가 올린 내용을 잘못 읽으신듯하네요.
그럼 위의 코드 에서 문제가 발생한단 말입니까? :D 그럼 음.
그럼 위의 코드 에서 문제가 발생한단 말입니까? :D
그럼 음.. key2, data2의 초기화는 어디서 하는가요?
DBT 초기화가 되지 않으면 에러가 발생합니다.
m.m
key2, data2는 여러가지로 테스트하다가 보니 잘못들어갓군요.. 수정했습니다.
첨 글에서
이런 메세지가 나왔습니다. 컴파일시에 에러도 아니고 커서 생성시에 반환값도 정상으로 나옵니다. 하지만 위 소스 코드처럼
while문에 c_get을 했을시에 데이터가 있음에도 불구하고 데이터가 없다는(DB_NOTFOUND) 메세지를 반환하는게
문제입니다. 아니면은 c_get에서 DB_SET나 DB_SET_RANGE옵션으로
데이터를 가져 올려고 하면은 "Cannot allocate memory"메세지를 출력합니다.
하지만 동일 소스를 그대로 main으로 가져가서 테스트 하면은 문제없이 데이터를 출력합니다.
[quote] [code:1]data.data = dstr;
위의 코드를 이렇게 한번 테스트 해보세요.
제가 업무중이라 테스트 는 안해봤습니다.
사용자 메모리 할당에서 최초 한번만 할당하고..
다음 레코드에서는 할당되지 않은 공간에다 기록할려고 시도하면서 에러가
발생한것 같습니다.
...
계속 봐주어서 고맙게 생각합니다...
말씀하신데로 테스트는 해봤는데 출력메세지는 동일하였습니다.
c_get에서 DB_NEXT 플래그를 줬을때는 데이터가 하나도 없다고 나오고..
DB_SET이나 DB_SET_RANGE 플래그로 c_get사용시에는 Cannot allocate memory 였습니다..
이런 글이 있네요..[quote]DB_DBT_USERMEM
이런 글이 있네요..
이걸 추가 시켜 실행하여 보시죠..
data.ulen = sizeof(StructDef);
m.m....
...
key,data가 사용되는곳에 .data, .size, .ulen, .flags 옵션을 다주고 커서 여는곳과 닫는곳을 한군데로 해서 하니 문제 없이 잘 동작합니다...
댓글 달기