1

現在、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: %s\nThe data is: %s\n", (char *)key.data, (char *)data.data);
}

何を追加する必要があるか教えてください。Berkeley DB に関するすべての情報が記載されている sourceforge ページを確認しましたが、私の知る限り、エントリの重複を許可するには DB->set_flags 行を追加するだけで済みますが、何か見落としがあるのでしょうか?

4

1 に答える 1

1

まず、関数が失敗する可能性がある場合は、常に戻り値を確認する必要があります。

具体的にdb_createset_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 %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つが正しくないことを意味します。

Web検索に基づくと、open呼び出しには5〜7個の引数の範囲でいくつかのバリエーションがあるようです。一部のOracleBDBdocoは、 5つの引数(データベースポインタもトランザクションポインタもなし)を取ると述べていますが、同じドキュメント(および他のOracle doco)のサンプルコードは7つの引数形式です。

BDBヘッダーファイルを調べて、どのヘッダーファイルを使用すべきかを確認することは価値があるかもしれません。

于 2012-04-05T04:42:15.280 に答える