代码的唯一区别是数据的初始化。这有效:

        Dbt key, data(&b, sizeof(int));
        key.set_data(&a);
        key.set_ulen(sizeof(int));
        data.set_flags(DB_DBT_USERMEM);

但这不是:
        Dbt key, data;
        key.set_data(&a);
        key.set_ulen(sizeof(int));
        data.set_data(&b);
        data.set_ulen(sizeof(int));
        data.set_flags(DB_DBT_USERMEM);

我阅读了https://docs.oracle.com/cd/E17076_04/html/api_reference/CXX/dbt.html中的文档,但没有看到这两种方式的区别。令人困惑。

完整的代码和结果如下所示:
$ cat db.cpp

#include <db.h>
#include <db_cxx.h>
#include <exception>
#include <iostream>
using namespace std;

int main() {
        Db db(NULL, 0);
        u_int32_t oFlags = DB_CREATE | DB_TRUNCATE;
        try {
            db.open(NULL, "test.db", NULL, DB_HASH, oFlags, 0);
        } catch (DbException &e) {
            cout << "DbException" << endl;
        } catch (std::exception &e) {

        }
        int a = 5, b = 6, c = 0, result[1]= {-1};
        Dbt key, data(&b, sizeof(int));
        key.set_data(&a);
        key.set_ulen(sizeof(int));
        data.set_flags(DB_DBT_USERMEM);
        cout << (db.get(NULL, &key, &data, 0) == DB_NOTFOUND) << endl;
        cout << c << endl;
        db.put(NULL, &key, &data, 0);
        key.set_data(&a);
        data.set_data(result);
        data.set_ulen(sizeof(int));
        cout << (db.get(NULL, &key, &data, 0) )<< endl;
        cout << *((int *) data.get_data()) << endl;
        cout << result[0] << endl;
        return 0;
}

$ rm test.db ; g++ db.cpp -ldb_cxx-5.1; ./a.out
1
0
0
6
6

$ cat db.cpp

#include <db.h>
#include <db_cxx.h>
#include <exception>
#include <iostream>
using namespace std;

int main() {
        Db db(NULL, 0);
        u_int32_t oFlags = DB_CREATE | DB_TRUNCATE;
        try {
            db.open(NULL, "test.db", NULL, DB_HASH, oFlags, 0);
        } catch (DbException &e) {
            cout << "DbException" << endl;
        } catch (std::exception &e) {

        }
        int a = 5, b = 6, c = 0, result[1]= {-1};
        Dbt key, data;
        key.set_data(&a);
        key.set_ulen(sizeof(int));
        data.set_data(&b);
        data.set_ulen(sizeof(int));
        data.set_flags(DB_DBT_USERMEM);
        cout << (db.get(NULL, &key, &data, 0) == DB_NOTFOUND) << endl;
        cout << c << endl;
        db.put(NULL, &key, &data, 0);
        key.set_data(&a);
        data.set_data(result);
        data.set_ulen(sizeof(int));
        cout << (db.get(NULL, &key, &data, 0) )<< endl;
        cout << *((int *) data.get_data()) << endl;
        cout << result[0] << endl;
        return 0;
}

$ rm test.db ; g++ db.cpp -ldb_cxx-5.1; ./a.out
1
0
0
-1
-1

最佳答案

您需要调用Dbt.set_size()Dbt.set_ulen()仅设置Dbt.data指向的内存的分配大小。 Dbt.size具有密钥或数据的实际使用长度。将这些调用添加到第二个示例中应该可以使其工作:

    Dbt key, data;
    key.set_data(&a);
    key.set_ulen(sizeof(int));
    key.set_size(sizeof(int));
    data.set_data(&b);
    data.set_ulen(sizeof(int));
    data.set_size(sizeof(int));
    data.set_flags(DB_DBT_USERMEM);

至于为什么Dbt key在没有set_size的情况下完全可以为您工作,我不确定。也许您对堆栈中未初始化的数据很幸运?如果您想找出答案,可以打印出key.size的值。

为了清楚起见,您不需要在ulen之前设置put()。仅在执行get()之前才需要设置它,以使BDB知道将数据读入其中需要多少内存。

关于c++ - Berkeley DB无法使用不同的Dbt初始化来设置值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38257424/

10-11 20:39