c++ - Function Scoped Static variables (Thread Unsafe in VC++)发生死锁

标签 c++ static deadlock

问题是在多线程调用函数时,函数级静态是如何构造的?

问题描述:发生死锁,我的应用程序没有终止。在局部静态变量的初始化过程中,它会尝试获取 MSVCR80!_lock 并且永远不会持有锁。

WinDbg 中的 !locks 命令提供以下输出。

CritSec ntdll!LdrpLoaderLock+0 at 7c97e178
锁定计数 0

递归计数 1

拥有线程 1998

条目数 d

竞争次数 d

*** 锁定

CritSec MSVCR80!__app_type+94 at 781c3bc8

锁定计数 1

递归计数 1

拥有线程 9a8

条目计数 1

ContentionCount 1

*** 锁定

下面是调用堆栈,你会看到它永远不会持有锁 _mlock

#

**

Call stack Thread 17e8

**

781c3bc8 78132bd9 0777fde4 ntdll!RtlEnterCriticalSection+0x46

00000008 b87d2630 00000000 MSVCR80!_lock+0x2e

0864ae10 08631d7f 0864ae10 EPComUtilities32!_onexit+0x36

0864ae10 b87d2588 00000001 EPComUtilities32!atexit+0x9

0777fea8 0864719f 08630000 EPComUtilities32!XCriticalSectionEx::ThreadTerminated+0x5f

08630000 00000003 00000000 EPComUtilities32!DllMain+0x20

08630000 7c90118a 08630000 EPComUtilities32!__DllMainCRTStartup+0x7a

08630000 00000003 00000000 EPComUtilities32!_DllMainCRTStartup+0x1d #

**

Call Stack thread 1100

**

000000b0 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc

000000b0 ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xa8

000000b0 ffffffff 06ce64e0 kernel32!WaitForSingleObject+0x12

000480ba 000f4240 00000000 CATSysMultiThreading!CATThreads::Join+0xf5

0012fcc8 00000004 00000000 JS0GROUP!CATLM::StopHB+0xf4

d138509f 00416694 00000001 JS0GROUP!CATLM::Unmake+0x6b

00000000 00000000 00000000 MSVCR80!_cinit+0xd6

00000000 0012fd6c 081e68d9 MSVCR80!exit+0xd

00000000 06d404f0 0998fb90 JS0GROUP!CATExit+0x1d

00000000 004ef366 0000000d DNBPLMProvider!DNBEPLMTransactionMgt::OnApplicationExit+0x229

00000000 0012fd9c 004eabfc JS0GROUP!CATCallExits+0x2bc

00000000 0012ff7c 0040cefd JS0GROUP!CATErrorNormalEnd+0x31 00000000 06ce71d0 06ce71d0 JS0GROUP!CATExit+0xc

00000007 06cdb120 059b61d8 DLMMfgContextSolver!main+0x146d

ffffffff ffffffff bffde000 DLMMfgContextSolver!__tmainCRTStartup+0x10f

// Code snippet below 
void main() 
{

    atexit(MyCallBack); 
    exit(0); 

}

void MyCallBack() 
{

// Waitingforsingleobject() // Waits until all threads are terminated

}

EXE 使用 DLL_THREAD_DETACH 标志调用 DllMain,我们有一个显式处理,如下所示

BOOL APIENTRY DllMain( HANDLE, DWORD dwReason, LPVOID ) 
{
  if(dwReason == DLL_THREAD_DETACH) 
  { 
    F1();
    F2();
  }
}

F1()
{

    const static CComBSTR bstrMethod = __ FUNCTION __ ;

}

F2()
{

    const static CComBSTR bstrMethod = __ FUNCTION __ ;

}

在函数中进行局部静态初始化是否线程安全。我还注意到,如果静态变量在主应用程序的 exit() 之前初始化过一次,我没有发现任何问题。谁能解释一下可能是什么问题?

注意:但是当我将静态变量设为非静态时,死锁不会发生,问题就解决了。

同时让我知道在这种情况下可能有帮助的任何替代解决方案 急切等待回复。

最佳答案

从某种意义上说,Vlad 对您的问题的评论已经回答了这个问题:不要在 DllMain 中做任何事情(如果可能的话)。

您确实受到 DllMain 中明智的限制,任何涉及深入研究另一个 Dll(包括使用 malloc 等)的东西都被淘汰了。事实上,您唯一可以做的事情是:调用 Kernel32.dll(加载/卸载 Dll 除外!)并初始化简单的数据类型。

我真的认为,鉴于您对问题的描述,使用 CComBSTR 违反了这些规则中的一个或多个。

希望对您有所帮助,

附:

来自 MSDN 博客的额外链接: http://blogs.msdn.com/oleglv/default.aspx

关于c++ - Function Scoped Static variables (Thread Unsafe in VC++)发生死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2339915/

相关文章:

C++如何使二维引擎平台独立

c++ time() 函数在 solaris 中的性能

android - android中的位图静态

ruby - 是什么导致我的 Ruby `trap` block 出现这种死锁?

c - Pthread程序死锁使用条件变量

sql-server - 识别 AWS RDS 上的 SQL Server 死锁

c++ - 如何设置 CMake 以与 Visual Studio 2017RC 和 CUDA 8.0 一起使用?

c++ - 使用 GCC 编译 WineMaker 生成的 MakeFile

Java:过度使用 'static'

java - 我应该使用静态绑定(bind)吗?