技术开发 频道

在Visual Studio 2005中使用 C++编程


如何运行ManWrap

  了解了Visual Studio 2005并不代表你能运行你能成功的运行你的代码。通常会发生捶墙,和砸电脑这些郁闷的情况。in the form of an ASSERT bomb way down in dbgheap.c:
     ASSERTE(_CrtIsValidHeapPointer(pUserData));
  栈跟踪几乎没有多大的作用,大量的系统dll组件没有运行调试记录。下面这种情况是最坏的漏洞和最难跟踪的:你的程序死机了,然而你找不到一丁点的线索。几乎是没有线索。当我编写代码试图去访问一个叫g_Allocator的静态ATL变量时,仔细检查栈跟踪就会显示50个页面。

  g_Allocator是一个静态的全局变量。初始化静态的C++变量是一件棘手的事情,特别是在DLLs组件中。在调用DllMain之前,编译器必须生成代码去调用CRT初始化函数来初始化你的静态变量。在自己熟悉的环境,做起事情就会如鱼得水,但是如果你的DLL组件去调用托管类,事情就会出现问题,你也许会遇到加载器死锁问题:操作系统试图加载你的dll组件时,你的应用程序就会停下来,这就是被我们所知的下载器被锁。总的来说,当你的DLL正在加载时,你不能加载所需要的DLL组件。举个常见的例子:当你调用::MessageBox诊断DllMain或者静态对象构造函数时,这个问题就会发生。

  为了避免下载器死锁,Visual Studio .NET 2003委托受控DLLs成为/NOENTRY DLLs(这种DLLs没有DllMain的入口点)。这就能保证下载器不会出现死锁的问题,但这时又会出现一个新的问题:现在静态变量不能初始化,因为Dll没有进行_DllMainCRTStartup,而由神奇的CRT函数来初始化他们。我在2005年二月份的栏目对此进行了详细地描述(msdn.microsoft.com/msdnmag/issues/05/02/CATWork)。没有静态对象是一个非常严重的问题,因为ATL 和MFC都要用到他们。没有DllMain,你就不能将受控代码和编写的代码混合封装成一个DLL组件,因为它又要用到ATL 和MFC.显然既然这是无法接受的,我们友好的Redmondtonians提供了一个特殊的文件<_vcclrit.h > ,这个文件包含了函数__crt_dll_initialize 和 __crt_dll_terminate(),通过调用这两个函数,你就可以初始化你的静态变量了。

  这听起来像一个小题大做的方法,它的确是这样的。 当你得知Visual Studio 2005解决了加载器死锁的问题后,你将会很高兴。你就不需要_vcclrit.h文件和/NOENTRY了,因为你现在可以正常的编译混合代码的DLLs组件了。想详细了解,请看这篇文章《Initialization of Mixed Assemblies》,网址是:
msdn2.microsoft.com/ms173266.aspx.
0
相关文章