0

调用 DB->put() 后,我在释放内存时遇到问题。当我这样做时,它说“双重免费或腐败”。

代码示例:

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);

C API 参考不包含有关该主题的任何信息,它仅提供有关在检索(但不存储)数据时使用 DB_DBT_MALLOC 的一些信息:

设置此标志时,Berkeley DB 将为返回的键或数据项分配内存(使用 malloc(3) 或用户指定的 malloc 函数),并在键或数据 DBT 的数据字段中返回指向它的指针结构体。因为任何分配的内存都成为调用应用程序的责任,所以调用者必须确定是否使用数据字段的返回值分配了内存。

当调用 DB->put 时,Berkeley DB 不返回任何数据,它只存储一个键/数据对。它是否复制数据,或者在调用 DB->close 或 ENV->close 之前内存是否应该存在?

4

1 回答 1

1

DB_DBT_MALLOC没有影响,db->put()因为db->put()将复制数据。所以你很可能在别处破坏你的堆。这种错误并不总是在它们引起的地方表现出来。我的猜测是您正在注销某个缓冲区的末尾。尝试在其上运行 Valgrind,跟踪此类问题通常非常有用。

我运行了这个简单的测试程序,它运行良好,valgrind 报告没有泄漏:

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;
}
于 2012-12-03T18:55:22.113 回答