C++ LevelDB在删除LevelDB实例时断言

C++ LevelDB在删除LevelDB实例时断言,c++,c++-cli,assert,assertions,leveldb,C++,C++ Cli,Assert,Assertions,Leveldb,当我试图删除leveldb实例时,我得到了一些非常恼人的断言,我不知道为什么会发生这种情况 断言发生在文件中: ExtStorage类如下所示: class AltStorage{ ExtStorage* instance; public: AltStorage(ExtStorage* extStorage):instance(extStorage){} ~AltStorage(){ delete instance; instance =

当我试图删除leveldb实例时,我得到了一些非常恼人的断言,我不知道为什么会发生这种情况

断言发生在文件中:

ExtStorage
类如下所示:

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

    ~AltStorage(){
        delete instance;
        instance = NULL;
    }
};
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 (
        }
    }
}
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;}
};
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();}
};
DotNet包装器如下所示:

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

    ~AltStorage(){
        delete instance;
        instance = NULL;
    }
};
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 (
        }
    }
}
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;}
};
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();}
};

每当我在我的C#应用程序中使用
ExtStorageDotNet
包装器时,一切都很好,没有断言。但是,当我使用
AltStorageDotNet
包装器并访问
ExtStorageDotNet
包装器时,我会在关闭数据库时获得断言这是测试套件的一部分,在测试套件中,我为每个测试用例初始化一个实例,并在每个测试用例之后关闭它;在新测试用例开始之前,关联的数据库文件会被删除。我看不出发生这种情况的任何原因,并且断言对跟踪问题没有帮助。

我不知道它是否与您的断言相关,但此代码肯定会导致内存损坏。
ExtStorageDotNet
AltStorageDotNet
都是一次性的和可终结的,并且都(直接或间接地)
delete
ExtStorage的实例-
ExtStorage
总是一个实例在另一个实例已经删除后将其删除


另外,正如我在评论中所说,代码中的评论说,
无需删除灭绝状态,因为它是用gcnew创建的,请参阅以获取详细信息。(我假设您了解C#,因此了解
IDisposable
;如果您不了解,那么您确实需要阅读一些内容。)

我去掉了嵌套引用,但这并没有解决问题。事实证明,导致这个问题的问题并不完全是我所看到的。当用户获得数据库的迭代器,但在删除数据库之前未能删除迭代器时,就会发生此问题。这是在一次讨论中讨论的


当用户获得迭代器时,他们应该在删除数据库之前删除迭代器,否则他们将得到上面提到的断言。

//无需删除灭绝,因为它是用gcnew创建的。
此评论非常误导。我无法删除灭绝,没有gcdelete。。。我可以将其设置为null,但仅此而已。“gcnew用于.NET引用对象;使用gcnew创建的对象会自动被垃圾收集;将gcnew与CLR类型一起使用非常重要”()不,没有
gcdelete
,但是
delete
在托管类型和非托管类型上具有完全不同的语义。您仍然应该使用它,并且在某些情况下需要--这可能是其中之一。那么自动垃圾收集呢?垃圾收集是关于内存管理的
IDisposable
是关于确定性终结的——出于您的目的,这些都是完全正交的概念。好吧,如果
delete
相当于空指针上的nop(这是我在删除指针后设置的),我看不出如何导致内存损坏。此外,根据,使用gcnew创建的对象会自动进行垃圾收集。@Lirik:您将
ExtStorageDotNet::instance
设置为
NULL
,但您认为这会如何影响
AltStorage::instance
(反之亦然)?另外,在本次讨论中,不要考虑垃圾收集,因为它与
IDisposable
;-]明白了:不需要删除
AltStorage::instance
@Lirik:不太清楚。:/您需要重新构造代码,以便只有一个对象拥有给定的非托管对象,并且需要
删除您在析构函数(但不是终结器)中拥有的托管对象。同样,请阅读一些关于
IDisposable
;有很多关于在MSDN上正确实现它的文章。好吧,我没有实现
IDisposable
,那么删除
AltStoragDotNet::Existance
对我有什么帮助呢?