2012-04-05 41 views
1

所以我目前正在通過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行來允許重複條目,但是可能會出現我錯過的東西?

+0

首先,當函數失敗時,應該_always_檢查返回值。這可能不是你的直接問題,但它仍然是一個好習慣。 – paxdiablo 2012-04-05 04:29:41

+0

好吧,所以我試圖獲得DBpointer-> c_get調用的返回值,但這是我得到分段錯誤的原因,所以我甚至不知道它是什麼。 :S即使我將它從while循環中取出並調用一次,仍然會出現錯誤。 – 2012-04-05 04:38:51

回答

1

首先,當函數失敗時,應該總是檢查返回值。

具體而言,db_createset_flagsopencursor所有返回一個錯誤指示。

如果您似乎在評論中指出這是導致SIGSEGV的c_get,那麼您可能希望確保光標的確已正確創建。

更改:

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時似乎有一些變化,範圍在5到7個參數之間。一些Oracle BDB doco指出它需要五個參數(沒有數據庫指針而不是事務指針),但同一文檔(和other Oracle doco)中的示例代碼具有七參數形式。

查看BDB頭文件以查看您應該使用哪一個可能是值得的。

+0

我認爲這可能是缺乏睡眠讓我,但我刪除了我的評論,因爲我看到你的答案的最後一部分具有相同的確切信息,因爲我的評論沒有,我想我沒有讀你的答案,但我只是意識到你編輯了你的答案以迴應我的評論。但在任何情況下,我都嘗試在引號中添加名稱(正如我在錯誤字段中所做的那樣),並通過打開文件然後傳遞指針,但每次我都無法編譯,因爲我' m從不兼容的參數類型中傳遞參數2。我該如何解決?爲什麼它在之前但不是現在起作用? – 2012-04-05 06:07:07

+0

@Gabe,去抓住你的'db.h'頭文件的原型行。這會告訴你使用正確的表單。 – paxdiablo 2012-04-05 06:14:07

+0

好吧,我通過從調用中移除參數(並且編譯器抱怨沒有足夠的參數輸入)並通過我們提供的很少的信息,我絕對使用了七個參數格式: open(student_db,NULL,「studentsdb」 ,NULL,DB_BTREE,DB_CREATE,0664),其中每個字段分別對應於: /*指向db結構的指針*/ /*事務指針*/ /*磁盤上數據庫的名稱*/ /* logical數據庫名稱(可選)*/ /*數據庫訪問方法*/ /*數據庫訪問方法*/ /* unix文件模式*/ – 2012-04-05 06:28:22