【发布时间】:2011-08-17 23:10:44
【问题描述】:
当我尝试删除 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
}
这里有更多关于我系统使用的背景细节,我有一个:
- 类
ExtStorage(扩展存储),它有一个LevelDB::DB实例。 -
EextStorageDotNet类,它是ExtStorage周围的 C++/CLI 包装器。 - class
AltStorage,它持有一个指向 ExtStorage 类的指针(通过构造函数传递): -
AltStorageDotNet类,它是AltStorage的 C++/CLI 包装器。
备用存储类如下所示:
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();}
};
每当我在我的 C# 应用程序中使用 ExtStorageDotNet 包装器时,一切正常,并且没有断言。但是,当我使用 AltStorageDotNet 包装器并访问 ExtStorageDotNet 包装器时,我会在关闭数据库时得到断言。 这是测试套件的所有部分,我在其中为每个测试用例初始化一个实例,并在每个测试用例后关闭它;在新的测试用例开始之前,相关的数据库文件会被删除。我看不出它应该发生的任何原因,并且断言对追踪问题没有帮助。
【问题讨论】:
-
// no need to delete extInstance since it was created with gcnew此评论非常误导。 -
我无法删除 extInstance,没有 gcdelete... 我可以将其设置为 null,但仅此而已。 "gcnew 用于 .NET 引用对象;使用 gcnew 创建的对象会自动进行垃圾回收;将 gcnew 与 CLR 类型一起使用很重要" (stackoverflow.com/questions/202459/what-is-gcnew/202464#202464)
-
不,没有
gcdelete,但delete在托管类型和非托管类型上的语义完全不同。您仍然应该使用它,并且在某些情况下需要——这很可能是其中一种情况。 -
自动垃圾回收呢?
-
垃圾收集是关于内存管理的;
IDisposable是关于确定性的最终确定——出于您的目的,这些是完全正交的概念。
标签: c++ c++-cli assert assertions leveldb