【问题标题】:Berkeley Database - Duplicate Entries Segmentation Fault伯克利数据库 - 重复条目分段错误
【发布时间】:2023-04-04 10:05:01
【问题描述】:

所以我目前正在通过 C 语言处理伯克利数据库,我遇到了一个关于允许重复数据的小问题。如果我不允许通过 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: %s\nThe data is: %s\n", (char *)key.data, (char *)data.data);
}

谁能告诉我我需要添加什么?我已经检查了包含有关 Berkeley DB 的所有信息的 sourceforge 页面,据我所知,我只需要添加 DB->set_flags 行以允许重复条目,但是我可能错过了什么吗?

【问题讨论】:

  • 首先,您应该始终在函数可能失败时检查返回值。这可能不是你眼前的问题,但它仍然是一个很好的做法。
  • 好的,所以我尝试获取 DBpointer->c_get 调用的返回值,但这就是我遇到分段错误的原因,所以我什至无法找出它是什么。 :S 即使我将它从while循环中取出并调用一次,我仍然会得到错误。

标签: c database segmentation-fault berkeley-db


【解决方案1】:

首先,当函数可能失败时,您应该始终检查返回值。

具体来说,db_createset_flagsopencursor全部返回错误指示。

如果正如您在评论中指出的那样,是 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 %p\n", rc, DBpointer);
fflush (stdio); // and possibly also: fsync (fileno (stdio));

会是一个好的开始。

最好是一路走,并使用类似的东西:

#define CHKERR(x) if(rc!=0){printf("%s err=%d\n",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: %s\nThe data is: %s\n", (char *)key.data, (char *)data.data);
}

根据您在公开调用中收到错误 22 的进一步评论,这是 EINVAL(至少在我的系统上),这意味着您的参数之一不正确。

根据网络搜索,open 调用似乎有一些变体,范围在五到七个参数之间。一些Oracle BDB doco 声明它需要五个 参数(没有数据库指针和事务指针),但同一文档(和other Oracle doco)中的示例代码有你的七参数形式。

可能值得查看您的 BDB 头文件以了解您应该使用哪个。

【讨论】:

  • 我认为这可能是我睡眠不足,但我删除了我的评论,因为我看到你答案的最后一部分与我的评论有相同的确切信息,我认为我没有没有阅读您的答案,但我刚刚意识到您编辑了您的答案以回应我的评论。但无论如何,我尝试在引号中添加名称(就像我在不正确的字段中所做的那样)和通过打开文件然后传递指针,但每次,我什至无法编译,因为我m 从不兼容的参数类型传递参数 2。我该如何解决?为什么以前有效,现在无效?
  • @Gabe,从db.h 头文件中获取原型线。这将告诉您使用的正确形式。
  • 好吧,我绝对是使用七参数格式,通过我从调用中删除参数(编译器抱怨输入的参数不足)以及通过我们得到的少量信息:open(student_db , NULL, “studentsdb”, NULL, DB_BTREE, DB_CREATE, 0664) 其中每个字段分别对应于: /* 指向数据库结构的指针 / / 事务指针 / /磁盘上数据库的名称 / / 逻辑数据库名称(可选)/ / 数据库访问方法 / / 数据库访问方法 / / unix 文件模式 */
  • 而且我对 linux 的了解还不够,甚至无法找到头文件并查看它,但这并不重要,因为我什至尝试过五参数模型并且编译器抱怨有几个参数类型不正确,并且传递的参数不足。
猜你喜欢
  • 1970-01-01
  • 2016-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多