在std :: condition_variable中调用后,由于INVALID PARAMETER导致应用程序崩溃 [英] Application crash due to INVALID PARAMETER after call in std::condition_variable

查看:240
本文介绍了在std :: condition_variable中调用后,由于INVALID PARAMETER导致应用程序崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用_beginthreadex生成大约20个线程的应用程序.所有线程都在等待填充的队列上,该队列是对std::queue:class MyQueue的包装.queue被创建为全局变量,类似于MyQueue processQueue

I have an application that spawns some 20 threads using _beginthreadex. All of the threads are waiting on a queue to be filled which is a wrapper over the std::queue : class MyQueue.The queue is created as a global variable something like MyQueue processQueue

MyQueuefront功能类似于

std::unique_lock<std::mutex> mlock(mutex_);
        while (queue_.empty())
        {
            cond_.wait(mlock);
        }
        auto item = queue_.front();
        queue_.pop();
        return item;

推送看起来像:

std::unique_lock<std::mutex> mlock(mutex_);
        queue_.push(item);
        mlock.unlock();
        cond_.notify_one();

cond_,queue_ and mutex_MyQueue的成员变量. 因此,最初,所有线程都处于等待状态.当queue有一个项目时,线程之一将读取它并对其进行处理. 正常或突然关闭应用程序时,会发生此问题. msvcr120!Concurrency::details::_Condition_variable::notify_all崩溃.

cond_,queue_ and mutex_ are member variable of MyQueue. So initially, all the threads are in waiting state. When the queue has an item, one of the thread reads it and process it. The problem occurs when the application is closed, gracefully or abruptly. There is a crash in the msvcr120!Concurrency::details::_Condition_variable::notify_all.

崩溃转储中的整个堆栈

ntdll!TppRaiseInvalidParameter+0x48
ntdll!TpAllocWait+0x6725f
kernel32!CreateThreadpoolWaitStub+0x1a
msvcr120!Concurrency::details::ExternalContextBase::PrepareForUse+0xa1
msvcr120!Concurrency::details::ExternalContextBase::ExternalContextBase+0xa2
msvcr120!Concurrency::details::SchedulerBase::AttachExternalContext+0xcf
Concurrency::details::SchedulerBase::CreateContextFromDefaultScheduler+0xfe
msvcr120!Concurrency::details::SchedulerBase::CurrentContext+0x26
msvcr120!Concurrency::critical_section::scoped_lock::scoped_lock+0x47
msvcr120!Concurrency::details::_Condition_variable::notify_all+0x23
msvcp120!_Cnd_destroy+0x1b
myfunction+0x36c501
msvcr120!doexit+0x145
msvcr120!__CRTDLL_INIT+0xce
ntdll!LdrpCallInitRoutine+0x41
ntdll!LdrShutdownProcess+0x142
ntdll!RtlExitUserProcess+0x78
KERNELBASE!DefaultHandler+0xf
KERNELBASE!CtrlRoutine+0x9b
kernel32!BaseThreadInitThunk+0xd
ntdll!RtlUserThreadStart+0x1d`

我尝试过的事情

  1. 使用std::unique_ptr作为条件变量,但不能解决问题.
  2. 调用队列dtor中的_endthreadex(0).这样可以解决退出时的崩溃问题,但是我不认为这是正确的方法,因为我不确定哪个线程正在关闭.
  1. use std::unique_ptr for the condition variable but it didn't fix the issue.
  2. call _endthreadex(0) in the dtor of the queue. This fixed the crash on exit, but i dont think this is the correct way as i am not sure which of thread is getting closed.

任何帮助将不胜感激.

推荐答案

这是crt错误.之所以崩溃,是因为std::condition_variable析构函数是从DLL_PROCESS_DETACH调用的.

this is crt bug. crash because std::condition_variable destructor called from DLL_PROCESS_DETACH.

MyQueue queue被创建为全局变量,而cond_被创建为全局变量 MyQueue

MyQueue queue is created as a global variable and cond_, are member variable of MyQueue

因为cond_是DLL中的全局对象-在DLL_PROCESS_DETACH

because cond_ is global object in DLL - it destructor called on DLL_PROCESS_DETACH

清晰可见,所有均从_Cnd_destroy开始(从条件变量的析构函数调用). crt内部调用 CreateThreadpoolWait .调用TpAllocWait.在此api的开头,存在下一行代码:

from stack trace clear visible that all begin from _Cnd_destroy (called from destructor of conditional variable). crt internally call CreateThreadpoolWait. which call TpAllocWait. at very begin of this api exist next line of code:

if (RtlGetCurrentPeb()->Ldr->ShutdownInProgress) TppRaiseInvalidParameter();

因为 CreateThreadpoolWait ExitProcess被调用之后调用(在堆栈跟踪ntdll!RtlExitUserProcess中查找)(在DLL_PROCESS_DETACH处理程序中)-ShutdownInProgress已经true并且结果被调用TppRaiseInvalidParameter-从堆栈跟踪中再次可见

because CreateThreadpoolWait called after ExitProcess called (look in stack trace ntdll!RtlExitUserProcess) (in DLL_PROCESS_DETACH handler) - the ShutdownInProgress already true and as result TppRaiseInvalidParameter called - again clear visible from your stack trace.

此处- std :: condition_variable析构函数在VS2012上崩溃此类崩溃的另一个示例. -如果您要查看崩溃的堆栈痕迹-您可以看到它完全相同(突出显示堆栈中的主要点)

here - std::condition_variable destructor crashes on VS2012 another example of this crash. - if you look to stack trace of the crash - you can view that it absolute the same (highlight main points in stack)

ntdll.dll!_NtRaiseException@12
  ntdll.dll!_KiUserExceptionDispatcher@8
  ntdll.dll!_TpAllocWait@16
  kernel32.dll!_CreateThreadpoolWait@12
  msvcp110d.dll!_Cnd_destroy(_Cnd_internal_imp_t * * cond) Line 35 C++
  ConnectModelUtil.dll!std::condition_variable::~condition_variable() Line 41 C++
  ConnectModelUtil.dll!_CRT_INIT(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 416 C
  ConnectModelUtil.dll!__DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 522 C

所以这里只有解决方案-不要在dll中使用全局condition_variable对象-否则您会在DLL_PROCESS_DETACH上崩溃

so only solution here - not use global condition_variable object in dll - otherwise you got crash on DLL_PROCESS_DETACH

也来自 std :: condition_variable ::〜condition_variable

程序员必须确保没有线程尝试等待* this 一旦析构函数启动

The programmer must ensure that no threads attempt to wait on *this once the destructor has been started

,但对于您而言,这是不正确的.您的线程在等待条件变量cond_.wait(mlock);的过程中终止.因此从条件变量的角度来看-线程仍在等待-它的数据(指向它的指针从它的堆栈中分配)链接到条件变量.您需要或以某种方式等待ExitProcess调用之前的所有线程-但您不能从DLL_PROCESS_DETACH之后执行此操作-为此exe必须在之前调用某些dll函数.还是不对dll全局条件变量使用wait

but this is not true in your case. your threads terminated during wait on conditional variable cond_.wait(mlock);. so from conditional variable view - threads still waiting - it data (pointers to it blocks allocated from it stack) linked to conditional variable. you need or somehow unwait all threads before ExitProcess call - but you can not do this from DLL_PROCESS_DETACH which is called after this - for this exe must call some dll function before. or not use wait on dll global conditional variable

这篇关于在std :: condition_variable中调用后,由于INVALID PARAMETER导致应用程序崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆