C++析构函数问题
我在 C++ 中有一个奇怪的“析构函数”行为
这是我调用的代码:
_log->OnCommit();
delete _log;
问题是当我调用“delete _log;”时它崩溃是因为变量“Entries”无效!!!!
你知道为什么吗?
这是我的班级代码:
struct TransactionLogEntry {
DependencyObject* Object;
bool IsAttached;
bool IsDeleted;
bool IsUpdated;
};
class TransactionLog
{
public:
TransactionLog();
~TransactionLog();
void OnCommit();
map<DependencyObject*, TransactionLogEntry*> Entries;
};
void TransactionLog::OnCommit()
{
map<DependencyObject*, TransactionLogEntry*>::iterator it;
for(it = Entries.begin(); it != Entries.end(); it++)
{
TransactionLogEntry* entry = (TransactionLogEntry*)(*it).second;
if (entry->IsDeleted)
delete entry->Object;
delete entry;
}
Entries.clear();
}
TransactionLog::~TransactionLog()
{
map<DependencyObject*, TransactionLogEntry*>::iterator it;
for(it = Entries.begin(); it != Entries.end(); it++)
{
TransactionLogEntry* entry = (TransactionLogEntry*)(*it).second;
delete entry;
}
Entries.clear();
}
I have a strange 'destructor' Behavior in C++
Here is the code I call :
_log->OnCommit();
delete _log;
The problem is that when I call "delete _log;" it crash because the variable 'Entries' is invalid !!!!
Do you know why ?
Here is my class code :
struct TransactionLogEntry {
DependencyObject* Object;
bool IsAttached;
bool IsDeleted;
bool IsUpdated;
};
class TransactionLog
{
public:
TransactionLog();
~TransactionLog();
void OnCommit();
map<DependencyObject*, TransactionLogEntry*> Entries;
};
void TransactionLog::OnCommit()
{
map<DependencyObject*, TransactionLogEntry*>::iterator it;
for(it = Entries.begin(); it != Entries.end(); it++)
{
TransactionLogEntry* entry = (TransactionLogEntry*)(*it).second;
if (entry->IsDeleted)
delete entry->Object;
delete entry;
}
Entries.clear();
}
TransactionLog::~TransactionLog()
{
map<DependencyObject*, TransactionLogEntry*>::iterator it;
for(it = Entries.begin(); it != Entries.end(); it++)
{
TransactionLogEntry* entry = (TransactionLogEntry*)(*it).second;
delete entry;
}
Entries.clear();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果没有完整的代码,很难看出,但是我可以注意到你违反了三巨头的规则(你有一个析构函数,但没有复制构造函数或赋值运算符),这意味着寻找麻烦。
我的大胆猜测是,您正在复制构建日志或其他类似问题,一旦您进入 UB 模式,那么任何事情都可能发生,包括在应该没问题的地方引发错误。
It's hard to see without complete code, however I can notice that you're violating the rule of the big three (you have a destructor, but no copy constructor or assignment operator) and this means looking for troubles.
My wild guess is that you're copy-constructing log or other similar problems and once you enter in UB mode then anything can happen, including raising errors in places that should be ok.
您是否在
Entries
映射中存储裸指针?如果是这样,您应该研究使用boost::shared_ptr
(或者tr1::shared_ptr
如果您有的话)。这极大地简化了存储管理(例如,您可以删除TransactionLog::OnCommit()
中的for
循环,而只需调用Entries.clear()
>。Are you storing naked pointers in the
Entries
map? If so, you should investigate usingboost::shared_ptr
(ortr1::shared_ptr
if youve got that) instead. This greatly simplifies storage management (for example you can delete thefor
loop inTransactionLog::OnCommit()
, and just callEntries.clear()
.如上所述,您缺少 TransactionLog 的复制构造函数和赋值运算符。这是问题的简化版:
这正确地分配和销毁了一个对象,对吗?不完全是:
这里是更接近您的代码的同一问题:
解决方案是为您的类声明一个复制构造函数和赋值运算符。即使您的类是“不可复制的”,您仍然应该声明它们,但将它们设为私有并且不要定义它们:
当它们是私有的时,任何使用(在不可访问的上下文中)都将是编译器错误。
As said, you're missing a copy ctor and assignment operator for TransactionLog. Here is the problem, simplified:
This properly allocates and destroys an object, right? Not quite:
And here is the same problem written more closely to your code:
The solution is to declare a copy ctor and assignment operator for your class. Even if your class is "non-copyable", you should still declare them, but make them private and don't define them:
When they are private, any use (in an inaccessible context) will be a compiler error.
看看 OnCommit 函数中的内容:
看起来像是检查某些内容是否被删除。如果是这样,您删除其中的某些内容并始终再次删除该对象。看起来你是在问问题。
Looking at what you have in the OnCommit function:
it looks like you check if something is deleted. If so, you delete something inside it and always delete the object again. Looks like you're asking for problems.
这里可能有2美分:
正如之前所说,尽量避免使用裸c/c++指针指向对象,而是使用某种智能ptr(例如boost::shared_ptr)或auto_ptr来简单地持有/释放资源(但是由于 auto_ptr 特定,所以不在 stl 容器中)
关于此崩溃:没有什么可以阻止您使用不同的键但相同的值填充地图对象。因此有可能删除对象两次或更多次,这肯定会导致崩溃(如果指针等于 0,则可以删除指针两次或更多次)。所以这样写:
删除指针;
ptr = 0;
而不是仅仅删除一个指针
here may 2 cents:
as it was said before, try to avoid using naked c/c++ pointers to objects, instead use some kind of smart ptr (e.g. boost::shared_ptr) or auto_ptr for simple holding/releasing resources (but not in stl containers due to auto_ptr specific)
about this crash: there is nothing to prevent you from filling map object with different keys but the same values. so it becomes possible to delete object twice or more times which definitely leads to crash (you can delete pointer twice or more if it is equal to 0). so write this:
delete ptr;
ptr = 0;
instead of just deleting a pointer