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 に答える