当我试图删除leveldb实例时,我得到了一些非常恼人的断言,我不知道为什么会发生这种情况!
断言发生在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包装器。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();}
};每当我在我的ExtStorageDotNet应用程序中使用C#包装器时,一切都很好,没有断言。但是,当我使用AltStorageDotNet包装器并访问ExtStorageDotNet包装器时,我在关闭数据库时得到断言。--这都是测试套件的一部分,在测试套件中,我为每个测试用例初始化一个实例,并在每个测试用例之后关闭它;关联的数据库文件在新的测试用例开始之前被删除。,我不知道它为什么会发生,断言对跟踪问题没有帮助。
发布于 2011-10-03 21:25:42
我去掉了嵌套的引用,但这并没有解决问题。事实证明,造成这一问题的并不完全是我在看的地方。当用户获得数据库的迭代器并在删除数据库之前无法删除迭代器时,就会发生此问题。这在一个与db级相关的google组中得到了讨论。
// 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; 当用户获得迭代器时,他们应该在删除db之前删除它,否则他们将得到上面提到的断言。
发布于 2011-08-17 23:31:38
我不知道它是否与您的断言相关,但这段代码肯定会导致内存损坏。ExtStorageDotNet和AltStorageDotNet都是一次性的和可终结的,两者(直接或间接)都是ExtStorage的实例--无一例外,一个会在另一个已经拥有的情况下将其delete化。
另外,正如我在我的评论中所说的,代码中的注释说no need to delete extInstance since it was created with gcnew是很遥远的--详细信息请参见这个答案。(我假设您了解C#,因此了解IDisposable;如果您不了解,那么您确实需要进行一些阅读。)
https://stackoverflow.com/questions/7100634
复制相似问题