ATL and the C
Runtime Library
By default, ATL projects link with the C runtime
library (CRT) in both debug and release configurations. Although
linking with the CRT increases the size of each ATL server, the CRT
provides useful functionality for memory management, string
manipulation, and exception handling. Additionally, the CRT is
responsible for calling the constructors of global objects when an
executable is loaded. As a result, constructing anything but the
most simplistic of projects without such important CRT
functionality is impractical.
In the spirit of allowing developers to minimize
the memory footprint of their COM servers, ATL provides a subset of
CRT functionality that can be used in place of the CRT itself. By
defining the preprocessor symbol _ATL_MIN_CRT, ATL
projects will not link with the CRT. You can define this symbol
from the project properties, as shown in Figure 5.2.
Setting Minimize CRT Use in ATL causes
_ATL_MIN_CRT to be defined and keeps your server from
linking with the CRT. It's important to realize that ATL does not
make available all the functions that the CRT provides when this
option is in use. If you happen to use a function that requires the
CRT when _ATL_MIN_CRT is defined, you'll get the following
somewhat cryptic linker error:
LIBCMT.LIB(crt0.obj) : error LNK2001:
unresolved external symbol _main
In ATL 3 and earlier, using _ATL_MIN_CRT left
out one very important feature of the CRT: static and global object
initialization. Global and static objects would not have their constructors or destructors
called. Thankfully, ATL 7 and later provide an implementation of
this feature even without CRT support. Inproc ATL servers include
an implementation of _DllMainCRTStartup that invokes
global constructors and destructors. ATL itself relies upon global
constructors and destructors in many key places throughout the
framework. For instance, in the discussion of ObjectMain
presented earlier in this chapter, I told you that ATL invokes
ObjectMain when a server initializes without explaining
precisely how this was done. With global constructors available
both with and without _ATL_MIN_CRT defined, ATL is
perfectly safe to invoke the ObjectMain methods of each
class in the object map by using the constructor of the global
CAtlModule instance:
template <class T>
class ATL_NO_VTABLE CAtlDllModuleT : public CAtlModuleT<T> {
public :
CAtlDllModuleT() {
_AtlComModule.ExecuteObjectMain(true);
}
~CAtlDllModuleT() {
_AtlComModule.ExecuteObjectMain(false);
}
...
}
|