библиотека cds: michael_deque вызывает сбой при возврате производного типа пользовательского типа (только в режиме выпуска)

Я использую VS2012 с настройками оптимизации по умолчанию (/ O2), и эта проблема существует только в режиме выпуска.

У меня есть код, который использует michael_deque (со стандартным GC) и указатель на (абстрактный) тип T,
Когда я пытаюсь отодвинуть указатель на тип, производный от Tприложение вылетает при выходе из push_back() функция michael_deque,

Проблема, кажется, зависит именно от этого конкретного типа Tпотому что написание фиктивного класса foo, исходя из этого в классе bar (и что-то печатать в конструкторе, чтобы избежать его оптимизации), а затем оттолкнуть new bar() to 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

};

Ошибка может быть воспроизведена в минимальной программе (если у вас есть среда, которая может выполнить это так же, как я, просто поместите 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, что вызывает проблемы в оптимизации?

3

Решение

Это была действительно ошибка компилятора. Более конкретно, это была ошибка, связанная с атомарной реализацией Visual Studio 2012.

Некоторые шаблонные специализации класса std :: atomic изменить указатель фрейма стека (ebp), не копируя его и не выталкивая его из стека до / после модификации. Библиотека libcds использует одну из этих специализаций, и получающийся в результате неправильный указатель фрейма иногда вызывает недопустимый доступ к памяти (кажется, что неопределенное поведение предотвращает катастрофический сбой в режиме отладки) при запуске вне области действия функции.

Исправление в этом особом случае состояло в том, чтобы 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

что заставит библиотеку постоянно использовать собственную реализацию атомарности.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]