Я сделал эту простую тестовую программу, и она иногда вызывает отладочный перерыв или просто вылетает (под Debug / Win32 / VS2010SP1) — и, конечно, иногда даже работает. Что-то я делаю не так или есть ошибка где-то в PPL (VS2010)?
#include "stdafx.h"#include <ppl.h>
#include <vector>
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<int> vi;
Concurrency::critical_section cs;
Concurrency::parallel_for(0, 10000, [&](int i)
{
Concurrency::critical_section::scoped_lock l(cs);
vi.push_back(i);
});
return 0;
}
Стек вызовов Debug Break выглядит следующим образом:
msvcr100d.dll! _CrtDbgBreak () Строка 85 C
msvcr100d.dll! _VCrtDbgReportW (int nRptType = 2, const wchar_t * szFile = 0x0f45d230, int nLine = 728, конст
msvcr100d.dll! _CrtDbgReportWV (int nRptType = 2, const wchar_t * szFile = 0x0f45d230, int nLine = 728, конст
msvcr100d.dll! _CrtDbgReportW (int nRptType = 2, const wchar_t * szFile = 0x0f45d230, int nLine = 728, const wchar_t * szModule = 0x00000000, const wchar_t * szFormat = 0x0 0 0 0 0 0 0 0 0 0 0 0) 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 за 0 по 0 в +45 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 за ушат на 0 на лож на ложно на ско
msvcr100d.dll! Параллелизм :: details :: LockQueueNode :: Copy (Параллелизм :: details :: LockQueueNode * pCopyFromNode = 0x7d92f908) Строка 728 + 0x27 байт C ++
msvcr100d.dll! Параллельность :: критическое_сечение :: _ Acquire_lock (void * _PLockingNode = 0x7d92f908, bool _FHasExternalNode = true) Строка 1019 C ++
msvcr100d.dll! Параллельное :: CRITICAL_SECTION :: scoped_lock :: scoped_lock (Параллелизм :: CRITICAL_SECTION & _Critical_section = заблокирован) Строка 1083 C ++
Lockable.exe!anonymous namespace'::<lambda0>::operator()(int i=1418) Line 14 + 0x11 bytes C++
анонимное пространство имен ‘::, 0> :: _ Invoke (const int & _First = 0, без знака int & _Index = 1418, постоянная
Lockable.exe!Concurrency::_Parallel_chunk_helper_invoke<int,unsigned int,anonymous-namespace'::<lambda0> & _Func={...}) Line 1445 C++
анонимное пространство имен ‘::, 0> :: operator () () Строка 1781 + 0x16 байт C ++
Lockable.exe!Concurrency::_Parallel_chunk_helper<int,unsigned int,
Lockable.exe! Concurrency :: task_handle, 0>>> (Concurrency :: task_handle, 0>> * _PChore = 0x7c13fba8 {_M_first = 0 _M_step = 1 _M_function = {…} …}) Строка 3495 C ++
msvcr100d.dll! Параллельность :: детали :: _ UnrealizedChore :: _ StructuredChoreWrapper (Параллельность :: детали :: _ UnrealizedChore * pChore = 0x7c13fba8 {_M_first = 0 _M_step = 1 _M_function = {…} …}) Строка 99 + 0c по C ++
msvcr100d.dll! Параллелизм :: подробности :: _ UnrealizedChore :: _ Invoke () Строка 3454 + 0xc байт C ++
msvcr100d.dll! Параллелизм :: детали :: WorkItem :: Invoke () Строка 75 C ++
msvcr100d.dll! Параллелизм :: детали :: InternalContextBase :: ExecuteChoreInline (Параллельность :: детали :: WorkItem * pWork = 0x7d92fe7c) Строка 1385 C ++
msvcr100d.dll! Параллелизм :: детали :: InternalContextBase :: Dispatch (Параллелизм :: DispatchState * pDispatchState = 0x7d92fe9c) Строка 1478 C ++
msvcr100d.dll! Параллелизм :: подробнее :: FreeThreadProxy :: Dispatch () Строка 157 C ++
msvcr100d.dll! Параллелизм :: details :: ThreadProxy :: ThreadProxyMain (void * lpParameter = 0x2ed5b4f0) Строка 162 C ++
kernel32.dll! 763c33aa ()
[Кадры ниже могут быть неправильными и / или отсутствующими, символы не загружены для kernel32.dll] ntdll.dll! 771a9ef2 ()
ntdll.dll! 771a9ec5 ()
Один сбой, который я только что получил, выглядит так, как будто блокировка не удерживалась (cs: not_locked)
Lockable.exe! Std :: vector> :: _ Orphan_range (int * _First = 0x0000c5db, int * _Last = 0x0000c5db) Строка 1442 + 0x5 байт C ++
Lockable.exe! Std :: vector> :: push_back (const int & _Val = 4177) Строка 995 C ++
Lockable.exe!
anonymous namespace'::<lambda0>::operator()(int i=4177) Line 16 C++
анонимное пространство имен ‘::, 0> :: _ Invoke (const int & _First = 0, без знака int & _Index = 4177, постоянная
Lockable.exe!Concurrency::_Parallel_chunk_helper_invoke<int,unsigned int,anonymous-namespace'::<lambda0> & _Func={...}) Line 1445 C++
анонимное пространство имен ‘::, 0> :: operator () () Строка 1833 + 0x16 байт C ++
Lockable.exe!Concurrency::_Parallel_chunk_helper<int,unsigned int,
Lockable.exe! Concurrency :: task_handle, 0>>> (Concurrency :: task_handle, 0>> * _PChore = 0x7cbffc24 {_M_first = 0 _M_step = 1 _M_function = {…} …}) Строка 3495 C ++
msvcr100d.dll! Параллельность :: детали :: _ UnrealizedChore :: _ StructuredChoreWrapper (Параллельность :: детали :: _ UnrealizedChore * pChore = 0x7cbffc24 {_M_first = 0 _M_step = 1 _M_function = {…} …}) Строка 99 + 0x на C ++
msvcr100d.dll! Параллелизм :: подробности :: _ UnrealizedChore :: _ Invoke () Строка 3454 + 0xc байт C ++
msvcr100d.dll! Параллелизм :: детали :: WorkItem :: Invoke () Строка 75 C ++
msvcr100d.dll! Параллельность :: детали :: InternalContextBase :: ExecuteChoreInline (Параллельность :: детали :: WorkItem * pWork = 0x7bc0fab4) Строка 1385 C ++
msvcr100d.dll! Параллельность :: детали :: InternalContextBase :: Dispatch (Параллелизм :: DispatchState * pDispatchState = 0x7bc0fad4) Строка 1478 C ++
msvcr100d.dll! Параллелизм :: подробнее :: FreeThreadProxy :: Dispatch () Строка 157 C ++
msvcr100d.dll! Параллелизм :: details :: ThreadProxy :: ThreadProxyMain (void * lpParameter = 0x2dcf6200) Строка 162 C ++
kernel32.dll! 763c33aa ()
[Кадры ниже могут быть неправильными и / или отсутствующими, символы не загружены для kernel32.dll] ntdll.dll! 771a9ef2 ()
ntdll.dll! 771a9ec5 ()
И даже внутри внутренней реализации PPL могут быть другие нарушения произвольного доступа, которые, я думаю, вы сможете воспроизвести. (с надеждой)
Я запустил ту же программу в Visual Studio 2012 Express для рабочего стола, и после многих тестовых запусков все работает нормально.
Мне интересно, если PPL под VS2010 глючит для использования в производственной среде?
Спасибо за любые вклады!
Итак, наконец, после публикации вопроса о Microsoft Connect (или Social?), Проблема была подробно объяснена.
На мой взгляд, вы должны ждать в конце программы. Рутина parallel_for
создал поток (ы) для одновременного выполнения и будет запускаться самостоятельно. Но main
выходит, что приведет к остановке всех запущенных потоков (или сделает их недействительными).
Попробуйте выполнить блокирующий вызов (такой же простой, как ввод пользователя), и посмотрите, работает ли он.