2012-04-05 3 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

まず、関数が失敗する可能性がある場合は常に_戻り値をチェックする必要があります。おそらくあなたの直面する問題ではないかもしれませんが、それはまだ良い習慣です。 – paxdiablo

+0

だから、DBpointer-> c_get呼び出しの戻り値を取得しようとしましたが、セグメンテーションフォルトが発生している理由がわかりません。 :S私がwhileループから取り出して一度呼び出すとしても、私はまだエラーが出ます。 –

答えて

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(:より良い

は、すべての道を行くと、のようなものを使用することです少なくともあなたのパラメータの1つが間違っていることを意味します)。

ウェブ検索に基づいて、openコールには5〜7つの引数のバリエーションがあります。一部のOracle BDB docoはの5つの引数(データベースポインターなしでトランザクションポインタではありません)がありますが、同じ文書内のサンプルコード(およびother Oracle doco)には7つの引数形式があります。

あなたのBDBヘッダーファイルを調べて、使用する必要があるファイルを調べることをお勧めします。

+0

私は睡眠不足の可能性があると思いますが、私のコメントは削除されました。あなたの答えの最後の部分は、私のコメントと同じ正確な情報を持っていたので、私はあなたの答えを読んでいないと思ったあなたが私のコメントに応じてあなたの答えを編集したことに気づきました。しかし、いずれにせよ、私は引用符で名前を追加すること(私は間違ったフィールドで行ったように)とファイルをfopen'ingし、ポインタを渡すことを試みたが、毎回私はコンパイルすることができない、引数2を互換性のない引数型から渡します。これをどうやって解決するのですか?それ以前はなぜ機能したのですか? –

+0

@Gabe、 'db.h'ヘッダファイルからプロトタイプの行を取得してください。それはあなたに正しい形式を教えてくれるでしょう。 – paxdiablo

+0

私は、コールからの引数を取り除いて7つの引数書式を使用しています。十分な引数が入力されていないことを告げるコンパイラとopen(student_db、NULL、 "studentsdb" 、NULL、DB_BTREE、DB_CREATE、0664)各フィールドはそれぞれ /*へのポインタ*/ /*トランザクションポインタ*/ /*ディスク上のデータベースの名前*/ /*論理*/ /*データベースアクセスメソッド*/ /*データベースアクセスメソッド*/ /* unixファイルモード*/ –