Question

I have a problem with deallocating memory after calling DB->put(). It says "double free or corruption", when I do it.

Code sample:

DBT key,value;
int err;
...
memset(value,0,sizeof(DBT));
value.data=malloc(10);
memset(value.data,10);
value.flags=DB_DBT_MALLOC;
...
value.size=10;
...
if((err=db->put(db,NULL,&key,&value,0))){
    ...
}
free(value.data);

The C API reference does not contain any information on the subject, it tells only some information about using DB_DBT_MALLOC when retrieving (but not storing) data:

When this flag is set, Berkeley DB will allocate memory for the returned key or data item (using malloc(3), or the user-specified malloc function), and return a pointer to it in the data field of the key or data DBT structure. Because any allocated memory becomes the responsibility of the calling application, the caller must determine whether memory was allocated using the returned value of the data field.

When DB->put is called, Berkeley DB does NOT return any data, it just stores a key/data pair. Does it copy the data, or should the memory be alife until DB->close or ENV->close is called?

Was it helpful?

Solution

DB_DBT_MALLOC has no effect in db->put() since db->put() will copy the data. So you are most likely corrupting your heap elsewhere. This kind of error doesn't always manifest itself where they were caused. My guess is that you're writing off the end of some buffer. Try running Valgrind on it, it's often very useful to track this kind of issue down.

I ran this simple test program and it works just fine and valgrind reports no leaks:

void test() {
    DB *DB;
    DBT key;
    DBT data;
    DBT value;
    int i;

    db_create(&DB, NULL, 0); 
    if(DB->open(DB, NULL, "tmp.db2", NULL, DB_BTREE, DB_CREATE, 0664) != 0) {
        printf("DB->open failed!\n");
        exit(0);
    }

    memset(&value,0,sizeof(value));
    value.size=10;
    value.data=malloc(value.size);
    memset(&key,0,sizeof(key));
    key.data=malloc(sizeof(unsigned int));
    key.size = sizeof(unsigned int);    
    for(i=0; i < 10; i++) {
        *(unsigned int*)key.data = i;
            memset(value.data, 0, value.size); /* valgrind complains if I leave this out? */
        sprintf(value.data, "test %d", i);

        if(DB->put(DB, NULL, &key, &value, 0 ) != 0) {
            printf("key stored failed\n");
            exit(-1);
        }
    }
    free(value.data);
    free(key.data);

    key.data = malloc(sizeof(unsigned int));
    key.size = sizeof(unsigned int); 
    *(unsigned int*)key.data=5;
    memset(&data,0,sizeof(data));
    data.flags = DB_DBT_MALLOC;
    DB->get(DB, NULL, &key,&data, 0);

    printf("size: %d data: %s\n", data.size, (const char*)data.data);
    DB->close(DB, 0);
    free(data.data);
    free(key.data);

    return;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top