【发布时间】:2013-08-31 17:27:07
【问题描述】:
我使用的是带有默认优化设置(/O2)的VS2012,这个问题只存在于发布模式。
我有一些代码使用michael_deque(使用标准GC)和指向(抽象)类型T的指针。
当我尝试将指针推回从T 派生的类型时,应用程序在退出michael_deque 的push_back() 函数时崩溃。
问题似乎完全取决于这种特定类型T,因为编写了一个虚拟类foo,从它派生到类bar(并在构造函数中打印一些东西以避免它被优化掉)然后将 new bar() 推回 michael_deque 不会导致崩溃。
有问题的班级T 是这样的:
class Task
{
public:
Task() : started(false), unfinishedTasks(1), taskID(++taskIDCounter) {};
Task(unsigned int parentID_) : started(false), unfinishedTasks(1), taskID(++taskIDCounter), parentID(parentID_)/*, taken(0)*/ {};
virtual ~Task() = 0 {};
virtual void execute() final
{
this->doActualWork();
unfinishedTasks--;
}
virtual void doActualWork() = 0;
public:
unsigned int taskID; //ID of this task
unsigned int parentID; //ID of the parent of this task
bool started;
std::atomic<unsigned int> unfinishedTasks; //Number of child tasks that are still unfinished
std::vector<unsigned int> dependencies; //list of IDs of all tasks that this task depends on
};
这个错误可以在一个最小的程序中重现(如果你碰巧有一个环境可以像我一样执行这个,只需在 Task 类可以看到的地方放一个std::atomic<unsigned int> taskIDCounter):
#include <cds/container/michael_deque.h>
#include "task.hpp"
class a : public Task
{
a()
{
std::cout<<"dummy print"<<std::endl;
}
virtual ~a()
{
}
virtual void doActualWork()
{
std::cout<<"whatever"<<std::endl;
}
};
int main()
{
cds::Initialize();
{
cds::gc::HP hpGC;
cds::gc::HP::thread_gc myThreadGC;
cds::container::MichaelDeque<cds::gc::HP,Task*> tasks;
tasks.push_back(new a()); //will crash at the end of push_back
}
cds::Terminate();
}
这可能是什么原因?我是否在类 Task 中做了一些未定义的事情,这会导致优化问题出现问题?
【问题讨论】:
-
在VS中不能调试吗?
-
调试模式下不会发生错误。在发布模式下,调试非常困难(即使激活了调试符号),因为该函数中的大部分内容都被优化掉了。
-
运气不好,崩溃的可能性是当我们取消引用一个悬空指针时。但我认为不是push_back引起的。
-
是的。当我在程序崩溃后停止程序时,应用程序当前正在退出 push_back 函数(可能在超出范围后解构某些东西)。但是,它并没有显示它在做什么。
-
您正在使用额外的一对大括号
{ }在本地范围内创建tasks容器。可能是cds:Terminate()试图释放已经释放的东西。