gpt4 book ai didi

c++ - 光盘库 : michael_deque causes crash when pushing back derived type of custom type (only in release mode)

转载 作者:太空狗 更新时间:2023-10-29 20:42:25 25 4
gpt4 key购买 nike

我使用的是默认优化设置 (/O2) 的 VS2012,这个问题只存在于 Release模式。

我有一些使用 michael_deque 的代码(使用标准 GC)和指向(抽象)类型的指针 T .
当我尝试将指针推回到派生自 T 的类型时,应用程序在退出时崩溃 push_back() michael_deque的功能.

问题似乎恰恰取决于这个特定类型 T , 因为写了一个虚拟类 foo , 从类中派生 bar (并在构造函数中打印一些东西以避免它被优化掉)然后推回 new bar()到 michael_deque 不会导致崩溃。

类(class)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

};

该错误可以在最小程序中重现(如果您碰巧有一个可以像我一样以相同方式执行此错误的环境,只需将 std::atomic<unsigned int> taskIDCounter 放在 Task 类可以看到它的地方):

#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 中做了一些未定义的事情,这会导致优化问题出现问题?

最佳答案

这确实是一个编译器错误。更具体地说,这是一个与 Visual Studio 2012 的原子实现相关的错误。

std::atomic 类的一些模板特化 modify the stack frame pointer (ebp) without backing it up on and popping it form the stack before/after the modification. libcds 库使用这些特化之一,并且在函数范围之外运行时,由此产生的不正确的帧指针有时会导致非法内存访问(未定义的行为似乎可以防止 Debug模式下的灾难性故障)。

在这种特殊情况下的解决方法是让 libcds 使用与 Visual Studio 提供的标准库不同的原子库。库决定在 cxx11_atomic.h 中使用哪个实现:

#if defined(CDS_USE_BOOST_ATOMIC)
# error "Boost.atomic is not supported"
//# include <boost/version.hpp>
//# if BOOST_VERSION >= 105300
//# include <boost/atomic.hpp>
//# define CDS_ATOMIC boost
//# define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace boost {
//# define CDS_CXX11_ATOMIC_END_NAMESPACE }
//# else
//# error "Boost version 1.53 or above is needed for boost.atomic"
//# endif

#elif CDS_CXX11_ATOMIC_SUPPORT == 1
// Compiler supports C++11 atomic (conditionally defined in cds/details/defs.h)
# include <cds/compiler/cxx11_atomic_prepatches.h>
# include <atomic>
# define CDS_ATOMIC std
# define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace std {
# define CDS_CXX11_ATOMIC_END_NAMESPACE }
# include <cds/compiler/cxx11_atomic_patches.h>
#else
# include <cds/compiler/cxx11_atomic.h>
# define CDS_ATOMIC cds::cxx11_atomics
# define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace cds { namespace cxx11_atomics {
# define CDS_CXX11_ATOMIC_END_NAMESPACE }}
#endif

if语句的第二个分支可以改成类似

#elif CDS_CXX11_ATOMIC_SUPPORT == 255

这将导致库始终使用其自己的原子实现。

关于c++ - 光盘库 : michael_deque causes crash when pushing back derived type of custom type (only in release mode),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18550883/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com