所以我目前正在通过C开发Berkeley数据库,遇到了一个关于允许重复数据的小问题。如果我不允许通过DB->set_flags重复条目,并且我用光标迭代数据库中的项目,那么一切都会很好。当我在程序中添加DB->set_flags行,而不更改其他内容时,我遇到了一个分段错误,我不知道如何修复它,因为它在没有重复条目的情况下工作得很好。代码如下:
DB *dates_db;
db_create(&dates_db, NULL, 0);
dates_db->set_flags(dates_db, DB_DUP);
dates_db->open(dates_db, NULL, "da.idx", NULL, DB_BTREE, 0, 0664);
DBT key, data;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
DBC *DBpointer;
dates_db->cursor(dates_db, NULL, &DBpointer, 0);
while(DBpointer->c_get(DBpointer, &key, &data, DB_NEXT) != DB_NOTFOUND)
{
printf("The key is: %snThe data is: %sn", (char *)key.data, (char *)data.data);
}
谁能告诉我我需要补充什么吗?我已经检查了包含Berkeley DB所有信息的sourceforge页面,据我所知,我只需要添加DB->set_flags行就可以允许重复条目,但可能有我遗漏的东西吗?
首先,当函数可能失败时,您应该始终检查返回值。
具体地,db_create
、set_flags
、open
、cursor
都返回错误指示。
如果像您在注释中指出的那样,是c_get
导致了SIGSEGV,那么您可能需要确保确实正确地创建了光标。
更改:
DBC *DBpointer;
dates_db->cursor(dates_db, NULL, &DBpointer, 0);
至:
DBC *DBpointer = (DBC*)0xdeadbeef;
int rc = dates_db->cursor(dates_db, NULL, &DBpointer, 0);
printf ("DEBUG: %d %pn", rc, DBpointer);
fflush (stdio); // and possibly also: fsync (fileno (stdio));
这将是一个良好的开端。
最好是一路使用类似的东西
#define CHKERR(x) if(rc!=0){printf("%s err=%dn",x,rc);fflush(stdout);exit(1);}
int rc;
DB *dates_db;
rc = db_create(&dates_db, NULL, 0);
CHKERR("create");
rc = dates_db->set_flags(dates_db, DB_DUP);
CHKERR("set_flags");
rc = dates_db->open(dates_db, NULL, "da.idx", NULL, DB_BTREE, 0, 0664);
CHKERR("open");
DBT key, data;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
DBC *DBpointer;
rc = dates_db->cursor(dates_db, NULL, &DBpointer, 0);
CHKERR("cursor");
while((rc = DBpointer->c_get(DBpointer, &key, &data, DB_NEXT)) != DB_NOTFOUND)
{
CHKERR("c_get");
printf("The key is: %snThe data is: %sn", (char *)key.data, (char *)data.data);
}
根据进一步的评论,您在开放调用中遇到错误22,这是EINVAL
(至少在我的系统中),这意味着您的一个参数不正确。
根据网络搜索,open
调用似乎有一些变体,范围在5到7个参数之间。一些Oracle BDB doco表示,它采用五个参数(没有数据库指针,也没有事务指针),但同一文档(和其他Oracle doco)中的示例代码具有七个参数形式。
查看您的BDB头文件,看看您应该使用哪一个可能是值得的。