删除LevelDB实例时LevelDB断言
当我尝试删除 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 包装器。 -
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
包装器时,我会在关闭数据库时收到断言。 这是测试套件的一部分,其中我为每个测试用例初始化一个实例,并在每个测试用例后关闭它;关联的数据库文件在新的测试用例开始之前被删除。 我看不出有任何原因会发生这种情况,并且断言对于追踪问题没有帮助。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我摆脱了嵌套引用,但这并没有解决问题。事实证明,导致这个问题的问题并不完全是我所关注的。当用户获取数据库的迭代器并且无法在删除数据库之前删除迭代器时,就会出现此问题。 与 level db 相关的 Google 群组对此进行了讨论。
当用户获取迭代器时,他们应该在删除数据库之前删除它,否则他们将得到上面提到的断言。
I got rid of the nested references, but that didn't solve the problem. As it turns out, the issue causing this problem was not quite where I was looking at. The issue occurs when a user gets an iterator to the database and fails to delete the iterator prior to deleting the database. This was discussed in a google group relating to level db.
When the user gets the iterator they should delete it prior to deleting the db, otherwise they will get the assertion mentioned above.
我不知道它是否与您的断言有关,但这段代码肯定会导致内存损坏。
ExtStorageDotNet
和AltStorageDotNet
都是一次性且可终结的,并且都(直接或间接)删除
ExtStorage
的实例 - - 总是,一个人会在另一个人已经删除它之后删除
它。另外,正如我在评论中所说,代码中的注释说
无需删除 extInstance,因为它是使用 gcnew 创建的
,这已经很离谱了——请参阅 此答案了解详细信息。 (我假设您了解 C#,因此了解IDisposable
;如果您不了解,那么您确实需要阅读一些内容。)I don't know whether it's related to your asserts or not, but this code is guaranteed to cause memory corruption. Both
ExtStorageDotNet
andAltStorageDotNet
are disposable and finalizable, and both (directly or indirectly)delete
the instance ofExtStorage
-- invariably, one willdelete
it after the other already has.Also, as I said in my comment, the comment in your code saying
no need to delete extInstance since it was created with gcnew
is way off -- see this answer for details. (I assume you know C# and thus aboutIDisposable
; if you don't, then you really need to do some reading.)