Search code examples
c++databasecaffelmdb

Bad Retrieval in LMDB Get?


I'm using lmdb database in my project, I have a problem in retrieving data with lmdb's mdb_get function...I am sure about the mdb_put is working correctly but the get function concatenate some garbage with my data...

std::string Get(std::string key)
{
    int rc=0;
    char *c_key=(char *)key.c_str();
    MDB_val d_key,data;
    data.mv_data = nullptr;
    data.mv_size = 0;
    MDB_txn *txn = nullptr;
    rc = mdb_txn_begin(env_, NULL,MDB_RDONLY, &txn);
    rc = mdb_dbi_open(txn,NULL, 0, &dbi_);
    d_key.mv_size =  key.size();
    d_key.mv_data = c_key;
    rc= mdb_get(txn,dbi_,&d_key,&data); 
    if (rc) {
     std::cout<<"Data Can't be Found, Error: "<<mdb_strerror(rc);
     mdb_dbi_close(env_,dbi_);
     return "";
    }
    else if(rc==0)
        std::cout<<"Data Found.\n";
    mdb_dbi_close(env_,dbi_);
    return (char *)data.mv_data;
}

the returned str contains some garbage like for example, str should contain "w ah n" but when I retrieved it mdb_get returns "w ah n\0004", it concatenates garbage after string null character.


Solution

  • The problem is this line:

    return (char *)data.mv_data;
    

    Because data.mv_data is actually just a bunch of bytes not a null-terminated string. If you just cast it to char* you can get garbage at the end of string.

    The solution is to copy data.mv_size bytes from data.mv_data to a newly allocated char*. Alternatively, you can pass the destination pointer as an out parameter of your Get method.

    At least this is my solution.