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

时间:2015-08-12 07:35:55

标签: visual-studio-2013 c++-cli windows-10

我有一个混合的托管和非托管C ++应用程序,它运行得很好。我使用Visual Studio 2013进行编译,一切都很顺利。最近我将计算机升级到Windows 10,现在它还没有运行。

如果我获得在Windows 8上编译的可执行文件,它可以在Windows 10上正常运行。只有在Windows 10上编译它才会失败。

失败也是特殊的。我运行EXE并没有任何反应。当我从Visual Studio运行它时,它甚至无法到达main的第一行。断点都标记为“禁用”。当我打破正在运行的进程时,调试器会显示一个空堆栈跟踪。

更新:关于DLL加载的预感变成了一个事实:

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

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

5 个答案:

答案 0 :(得分:2)

这是一个名为“LoaderLock”的通用问题。操作系统在调用DLL的DllMain()入口点时会提供非常强大的保证。严格按装载顺序,它们从不同时运行。 OS加载程序中有一个锁,可以确保保留这些承诺。

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

您只能使用调试器查看它。你必须改变它的味道,Project>属性>调试>调试器类型,将其从“自动”更改为“混合”。您现在还将看到正在运行的非托管代码,包括OS加载程序函数,名称以“Ldr”开头。请务必使用工具>启用Microsoft Symbol Server。选项>调试>符号。并确保使用Debug> Windows>线程调试窗口,真正棘手的加载器死锁,不能很好地重复或似乎受操作系统版本的影响,是由另一个加载DLL的线程引起的。

诊断和修复它可能很困难,请务必保留您需要挖掘的时间。如果您无法制作堆栈痕迹的头部或尾部,请将它们发布在您的问题中。

答案 1 :(得分:2)

在接受@Hans Passant建议之前,我仔细梳理了代码,dumpbin /dependents编了可执行文件和DLL,并确保没有自定义DllMains。没有。 DLL确实加载了LoadLibrary,但是在加载加载DLL之后很久就发生了这种情况。

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

找到传递给LdrLoadDll的DLL的名称花了一点时间。这是AVGHOOK.DLL。

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

这是AVG第二次搞砸我。上次我几乎更换了打印机,直到我发现当我禁用AVG时所有PCL错误都消失了。我想我不会再使用它了。

答案 2 :(得分:1)

我已将评论乒乓写入全文:

#1:
如您所知,您的应用程序未加载,您需要检查系统上的应用程序(W10,VS2013)是否完全运行。
回复:测试控制台应用运行正常。

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

#3:
在测试应用程序中仅引用此DLL以确保它仅是此DLL,而不是DLL的组合 它是托管DLL还是本机C ++ DLL? 如果有缺陷的DLL来自外国来源:运气不好。请开发者寻求支持 如果它是您自己的:您是否也在W10 + VS2013上编译了错误的DLL,或者您是否从以前的系统中复制了它?我建议你在新系统上再次编译这个DLL 回复:它是一个原生C ++ DLL,它是解决方案的一部分,并与主应用程序一起编译。

  

不幸的是,这个DLL引用了其他DLL。

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

答案 3 :(得分:0)

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

在我们的案例中,反病毒Avast正在破坏生成的.exe!

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

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

答案 4 :(得分:0)

这个问题在Windows 10中有点令人恼火。没有关于它的警告,但防病毒是罪魁祸首。我一直在使用avast。我可以通过暂时关闭盾牌来修复它。但是,永久的解决方案在于将程序或 .exe 文件添加到Avast的whiteList中,如下所示

http://www.getavast.net/support/managing-exceptions