0

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?

Pupkov-Zadnij
  • 1,342
  • 2
  • 11
  • 21
  • Can you include a code sample (the smaller the better) which demonstrates this problem please? – simonc Dec 03 '12 at 15:25
  • @simonc Code sample is added. – Pupkov-Zadnij Dec 03 '12 at 15:48
  • 1
    Sorry, I can't say what the error is. There are a few things you could investigate though... Many of the fields of key & value are left uninitialised; most of these fields appear to have some significance to put(). You could try initialising all fields of value and the ones [the docs](http://docs.oracle.com/cd/E17076_02/html/api_reference/C/dbt.html) suggest are relevant for key. You could also check the error return from db->put() to see if that gives any hints about your error. – simonc Dec 03 '12 at 16:18
  • @simonrc This is what I actually do, I have edited the code fragment to show it. – Pupkov-Zadnij Dec 03 '12 at 17:08

1 Answers1

1

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;
}
Gille
  • 5,693
  • 1
  • 17
  • 16