代码的唯一区别是数据的初始化。这有效:
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/