C++/CLI 应用程序在 Windows 10 上编译后挂起

C++/CLI application hanging after compiling on Windows 10

我有一个运行良好的混合托管和非托管 C++ 应用程序。我用的是 Visual Studio 2013 编译的,一切正常。最近我把我的电脑升级到Windows10,现在不能用了。

如果我在 Windows 8 上编译了可执行文件,它会在 Windows 10 上正确 运行s。只有在 Windows 10 上编译它才会失败。

故障也很特殊。我 运行 EXE 没有任何反应。当我从 Visual Studio 运行 它甚至没有到达 main 的第一行时。断点都标记为'disabled'。当我中断 运行ning 进程时,调试器显示一个空的堆栈跟踪。

更新:关于 D​​LL 加载的预感变成了事实:

我使用了 Process Explorer,我看到进程有两个线程。从 !CorExeMain 开始的那个卡在 !LdrLoadDll,但我无法分辨是哪个 DLL。

好的,找到导致问题的DLL。我创建了一个 C++/CLI 控制台应用程序,使用了该 DLL 并获得了相同的行为。 DLL 是应用程序的一部分(也是 VS 解决方案的一部分)。它是一个本地 C++ DLL,使用相同的编译器和设置编译。不幸的是,此 DLL 引用 其他 个 DLL。

这是一个名为 "LoaderLock" 的通用问题。操作系统在调用 DLL 的 DllMain() 入口点时会做出非常有力的保证。严格按照加载顺序,它们绝不会同时 运行。 OS 加载程序中有一个锁,可确保遵守这些承诺。

而锁总是有可能导致死锁的。当 DllMain() 入口点做了一些不明智的事情,比如用 LoadLibrary() 加载 DLL 本身时,就会发生这种情况。或者调用一个需要 OS 的函数来加载一个 DLL。不能工作,它的 DllMain() 入口点不能被调用,因为装载程序锁被持有。该程序将冻结。 C++/CLI 应用程序很容易出现这个问题,很多事情往往发生在 DllMain() 中。间接地,您无法在代码中看到它。

只能用调试器才能看到。您必须更改其风格,Project > Properties > Debugging > Debugger Type,将其从 "Auto" 更改为 "Mixed"。您现在还会看到 运行ning 的非托管代码,包括 OS 加载程序函数,名称以 "Ldr" 开头。请务必使用工具 > 选项 > 调试 > 符号启用 Microsoft 符号服务器。并且一定要使用 Debug > Windows > Threads debugging window,真正棘手的加载程序死锁不会很好地重复或似乎受到 OS 版本的影响由另一个线程加载 DLL。

诊断和修复它可能很困难,请务必预留您需要深入研究的时间。如果您无法确定堆栈跟踪的正面或反面,那么 post 将它们放在您的问题中。

我已经把我们的评论乒乓成全文了:

#1:
正如您发现的那样,您的应用程序没有加载,您需要检查系统上的应用程序(W10、VS2013)运行。
回复: 测试控制台应用 运行 没问题。

#2:
如果您的应用程序没有 运行,请构建一个类似的应用程序,并逐步将您应用程序的代码放入新应用程序,直到它失败。
如果失败是由 DLL 引起的(无法加载,就像您的情况一样),请从您的应用程序中删除 DLL 直到它工作。或者构建一个虚拟控制台应用程序,包括 DLL #1 并使用该 DLL 的一些功能。编译,运行,检查。继续直到 DLL #n...
回复: 发现错误的 DLL。

#3:
在测试应用程序中仅引用此 DLL,以确保它只是此 DLL 而不是 DLL 的组合。
它是托管 DLL 还是本机 C++ DLL?
如果有故障的 DLL 来自外部来源:运气不好。向开发者寻求支持。
如果是你自己的:这个错误的DLL是你在W10+VS2013上也编译的,还是从你以前的系统上拷贝过来的?我建议你在新系统上重新编译这个DLL。
回复:它是本机 C++ DLL,是解决方案的一部分,与主应用程序一起编译。

This DLL references other DLLs unfortunately.

#4:
创建一个新的控制台应用程序,它引用的不是您的错误应用程序 DLL,而是您的 DLL 引用的 DLL。省略检测故障是否来自其他 DLL 的中间步骤。
一般程序是:将错误的代码拆分,找出是哪一部分造成了问题。罗马人在 2000 年前就已经知道这一点:Divide et impera ;-) 虽然他们是在不同的背景下做的...

在接受@Hans Passant 的建议之前,我仔细梳理了代码,dumpbin /dependents编辑了可执行文件和 DLL,并确保没有自定义 DllMain。有 none。 DLL 确实是用 LoadLibrary 加载的,但那是在加载加载 DLL 很久之后才发生的。

所以我接受了@Hans Passant 的建议。正确设置调试器并检查死锁期间进程的状态。其中一个线程卡在 LdrLoadDll 中。

费了点功夫才找到传递给 LdrLoadDll 的 DLL 的名称。这是 AVGHOOK.DLL .

我禁用了 AVG,你瞧 - 一切都恢复正常了。

这已经是AVG第二次惹我了。上次我几乎要更换打印机,直到我发现禁用 AVG 后所有 PCL 错误都消失了。我想我不会再用它了。

几周来我们在这里遇到了完全相同的问题!我们终于找到了解决方案!

在我们的案例中,是反病毒软件 Avast 破坏了生成的 .exe!

解决方案是在生成版本时简单地禁用所有代理!

如果您使用其他防病毒软件,请尝试将其禁用。