Berkeley DB не может установить значение с другой инициализацией Dbt

Единственное отличие кода — это инициализация данных. Это работает:

        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

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 знать, сколько памяти нужно для чтения данных.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]