Berkeley DB не может получить доступ к данным без закрытия базы данных

Я пытаюсь использовать berkeley DB для хранения и получения простых пар ключ/данные, но это не работает, как я ожидал. Я создаю одну функцию (putdb()) для помещения пары ключ/данные в базу данных и другую (getdb()) для извлечения этой пары.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <db.h>
DB *dbp;
void opendb(void)
{
        int ret; 
        if ((ret = db_create(&dbp, NULL, 0)) != 0)
                exit(EXIT_FAILURE);
        if ((ret = dbp->open(dbp, NULL, "db.db", NULL,DB_BTREE, DB_CREATE, 0664)) != 0)
                exit(EXIT_FAILURE);
}


void putdb(const char *key, const char *value)
{
    DBT keyValue, dataValue;
    memset(&keyValue, 0, sizeof(keyValue));
    memset(&dataValue, 0, sizeof(dataValue));

    keyValue.size = sizeof(key);
    dataValue.size = sizeof(value);

    keyValue.data = malloc(keyValue.size);
    strcpy(keyValue.data,key);

    dataValue.data = malloc(dataValue.size);
    strcpy(dataValue.data,value);

    if ((ret = dbp->put(dbp, NULL, &keyValue, &dataValue, 0)) == 0)
            printf("db: %s: key stored.\n", (char *)keyValue.data);
    else {
            dbp->err(dbp, ret, "DB->put");
    }
    dbp->sync(dbp, 0);
}

void getdb(const char *key,const char *value)
{
    DBT keyValue, dataValue;
    memset(&keyValue, 0, sizeof(keyValue));
    memset(&dataValue, 0, sizeof(dataValue));

    keyValue.size = sizeof(key);
    dataValue.size = sizeof(value);

    keyValue.data = malloc(keyValue.size);
    strcpy(keyValue.data,key);

    dataValue.data = malloc(dataValue.size);
    strcpy(dataValue.data,value);

    if ((ret = dbp->get(dbp, NULL, &keyValue, &dataValue, 0)) == 0)
            printf("db: %s: key retrieved: data was %s.\n",
                (char *)keyValue.data, (char *)dataValue.data);
    else {
            dbp->err(dbp, ret, "DB->get");
    }
}
void closedb(void)
{
    dbp->close(dbp, 0);
    //TODO : error code return check
}

и основной файл:

int main()
{
    opendb();
    putdb("toto","titi");
    getdb("toto","titi");
    closedb();
 }

и я получаю:

db: toto: key stored.
DB->get: BDB0073 DB_NOTFOUND: No matching key/data pair found

Можете ли вы объяснить, почему?

Обратите внимание, если я изменю свою основную функцию:

int main()
{
    opendb();
    putdb("toto","titi");
    closedb();
    opendb();
    getdb("toto","titi");
    closedb();
}

тогда это работает! :

db: toto: key stored.
db: toto: key retrieved: data was titi.

person sebastien dontneedtoknowthat    schedule 04.09.2016    source источник
comment
По какой причине вы добавили тег C++?   -  person too honest for this site    schedule 04.09.2016
comment
Если вы используете 32-битную платформу, вы пишете за пределами своих выделений, что является Неопределенным поведением. В 64-битных архитектурах вы читаете неинициализированную память, которая также является UB, и вполне вероятно, что это приведет к ошибкам key not found. Во всех случаях у вас происходит утечка памяти. Возможно, вы захотите исправить эти проблемы, даже если это не решит насущную проблему (хотя и может).   -  person rici    schedule 04.09.2016


Ответы (1)


Вы слишком много скопировали из учебника. Они могут использовать sizeof("a string"), но вы должны использовать strlen(key) как в putdb, так и в getdb.

keyValue.size = strlen(key);
dataValue.size = strlen(value);
person deamentiaemundi    schedule 04.09.2016
comment
Обычно вы не будете предоставлять значение данных при извлечении ключа. getdb("key", "value") предполагает, что OP не нужно знать немного больше о хранилищах данных. :) - person rici; 04.09.2016
comment
@rici yepp, как я уже заметил, вы слишком много скопировали из учебника. Это было слишком тонко? - person deamentiaemundi; 04.09.2016
comment
Я не знаю, о каком туториале вы говорите, но если, например, malloc и strcpy были скопированы, то это очень плохой туториал, и его следует избавить от страданий при первой же возможности. К сожалению, такие антитуториалы существуют, но я подозреваю, что это не случай чрезмерного копирования, а скорее чрезмерная разработка, возможно, основанная на каком-то ранее ассимилированном карго-культе. В любом случае, минимальное противоядие, вероятно, представляет собой простой копируемый пример. - person rici; 04.09.2016
comment
@rici Я думаю, что это из официального учебника, подобного тому, который можно найти здесь: web.stanford.edu/class/cs276a/projects/docs/berkeleydb/ (или более поздняя версия). Я не знаю, что делать с противоядием, но думаю, что попробую. - person deamentiaemundi; 04.09.2016
comment
oO Мне стыдно за свою ошибку!! Конечно, я не могу использовать sizeof для указателей. Теперь это работает. большое вам спасибо. - person sebastien dontneedtoknowthat; 04.09.2016
comment
Большая часть кода, который я пишу в своем сообщении, действительно взята из официального учебника. malloc() и strcpy() не взяты из учебника и полезны для других целей (я не поместил весь свой код в сообщение), но здесь они совершенно бесполезны, я согласен. Я думаю, что учебник хорош, но мой код был просто очень плохим. - person sebastien dontneedtoknowthat; 04.09.2016