LevelDB утверждается при удалении экземпляра LevelDB - PullRequest
2 голосов
/ 18 августа 2011

Я получаю некоторые очень раздражающие утверждения, когда пытаюсь удалить экземпляр leveldb, и я не уверен, почему это происходит!

Утверждение происходит в файле version_set.cc :

void VersionSet::AppendVersion(Version* v) {
  // Make "v" current
  assert(v->refs_ == 0); // <---??? how do I avoid this assertion?
  // the rest of the source code is available in the link to version_set.cc
}

Кроме того, он утверждает в другом месте в том же файле:

Version::~Version() {
  assert(refs_ == 0); // <-- Again... how do I avoid this one too?
  // the rest of the source code is available in the link to version_set.cc
}

Вот дополнительные сведения об использовании в моей системе, у меня есть:

  • class ExtStorage (Extended Storage) с экземпляром LevelDB::DB.
  • class EextStorageDotNet, который является оболочкой C ++ / CLI для ExtStorage.
  • class AltStorage, который содержит указатель на класс ExtStorage (переданный через конструктор):
  • class AltStorageDotNet, который является оболочкой C ++ / CLI для AltStorage.

Альтернативный класс хранения выглядит следующим образом:

class AltStorage{
    ExtStorage* instance;
public:
    AltStorage(ExtStorage* extStorage):instance(extStorage){}

    ~AltStorage(){
        delete instance;
        instance = NULL;
    }
};

Класс ExtStorage выглядит следующим образом:

class ExtStorage{
    leveldb::DB* mydb;
public:
    ExtStorage(/*some parameters*/){
         mydb = new leveldb::DB(/*parameters*/);
    }

    // Destructor
    ~ExtStorage() {
        Close();
    }

    // deletes the leveldb::DB instance
    void Close() {
        if(mydb == NULL) {
            delete mydb; // <-- Asserts every time I get here when using with the AltStorageDotNet
            mydb= NULL;

            // Close the L1 and L2 caches
            // only once (
        }
    }
}

Класс AltStorageDotNet выглядит следующим образом:

public ref class AltStorageDotNet{
    AltStorage* altInstance;
    ExtStorageDotNet^ extInstance;
public:
    AltStorageDotNet() {
        ExtStorage extStorage = new ExtStorage(/*params*/);
        altInstance = new AltStorage(extStorage);
        extInstance = gcnew ExtStorageDotNet(extStorage);
    }

    ~AltStorageDotNet(){
        delete altInstance;
        altInstance = NULL;
        // no need to delete extInstance since it was created with gcnew 
    }

    !AltStorageDotNet(){
        delete altInstance;
        altInstance = NULL;
        // no need to delete extInstance since it was created with gcnew
    }

    inline ExtStorageDotNet^ GetExtInstance(){return extInstance;}
};

Оболочки DotNet выглядят так:

public ref class ExtStorageDotNet{
private:
    ExtStorage* instance;
public:
    ExtStorageDotNet(ExtStorage* extStorage){
        instance = extStorage;
    }

    ~ExtStorageDotNet(){
        delete instance;
        instance = NULL;
    }

    !ExtStorageDotNet(){
        delete instance;
        instance = NULL;
    }

    void Close(){instance->Close();}
};

Всякий раз, когда я использую обертку ExtStorageDotNet в своем приложении C # каждыйвещь работает хорошо, и нет никаких утверждений.Однако, когда я использую оболочку AltStorageDotNet и получаю доступ к оболочке ExtStorageDotNet, я получаю утверждения при закрытии базы данных. Это все часть набора тестов, в котором я инициализирую экземпляр для каждого теста и закрываю его после каждого теста;связанные файлы базы данных удаляются до начала нового теста. Я не вижу причин, по которым это должно происходить, и утверждение не помогает в поиске проблемы.

Ответы [ 2 ]

2 голосов
/ 04 октября 2011

Я избавился от вложенных ссылок, но это не решило проблему. Как оказалось, проблема, вызвавшая эту проблему, была не совсем той, на которую я смотрел. Эта проблема возникает, когда пользователь получает итератор в базу данных и не может удалить итератор до удаления базы данных. Это обсуждалось в группе google, связанной с уровнем db .

// Caller should delete the iterator when it is no longer needed.
// The returned iterator should be deleted before this db is deleted.
virtual Iterator* NewIterator(const ReadOptions& options) = 0; 

Когда пользователь получает итератор, он должен удалить его до удаления БД, в противном случае он получит утверждение, упомянутое выше.

1 голос
/ 18 августа 2011

Я не знаю, связано ли это с вашими утверждениями или нет, но этот код гарантированно вызовет повреждение памяти.И ExtStorageDotNet, и AltStorageDotNet являются одноразовыми и финализируемыми, и оба (прямо или косвенно) delete экземпляр ExtStorage - неизменно один будет delete после того, как другой уже имеет.

Кроме того, как я уже сказал в своем комментарии, комментарий в вашем коде, говорящий о no need to delete extInstance since it was created with gcnew, далек от этого - подробности см. в этом ответе .(Я предполагаю, что вы знаете C # и, следовательно, о IDisposable; если нет, то вам действительно нужно немного почитать.)

...