C++ LevelDB在删除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 =
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
对我有什么帮助呢?