Единственное отличие кода — это инициализация данных. Это работает:
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 знать, сколько памяти нужно для чтения данных.
Других решений пока нет …