This usually happens when the C Run-Time (CRT) startup code
is required for some CRT functions. You can either remove
all references to the CRT functions that require the
startup code or remove the _ATL_MIN_CRT preprocessor
definition from your compiler settings.
You can link statically or dynamically to the CRT.
Statically linking causes the CRT code to be placed in your
executable image and you do not need to have the CRT DLL
(Msvcrt.dll). If you dynamically link to the CRT,
references to the code in Msvcrt.dll are placed in your
image. For your image to run, Msvcrt.dll must be present.
Even when dynamically linking to the CRT, there can still
be some code statically linked, such as DllMainCRTStartup.
An entry point, explicitly or implicitly specified when
linking, is called by the operating system after loading
the image. For a DLL, the default entry point is
DllMainCRTStartup. For an EXE, it is WinMainCRTStartup. You
can override the default with the /ENTRY linker option. The
CRT provides an implementation for DllMainCRTStartup,
WinMainCRTStartup, and wWinMainCRTStartup (UNICODE entry
point for an EXE). These entry points (CRT startup code)
call constructors on global objects and initialize some
data structures used by some CRT functions. This startup
code adds about 25K to your image when statically linking.
Some CRT functions can be used without the CRT startup
code, for example, functions with the mem prefix, wcslen,
wcscmp, and strlen. The following require the CRT startup
code: • String comparison routines
• Memory allocation routines
• Global objects with constructors
• C++ exception handling (/GX)
ATL is aimed at minimizing the image size and the reliance
on run-time DLLs. It provides alternative implementations
for common CRT APIs that would otherwise require the CRT
startup code. The use of these APIs is controlled by the
_ATL_MIN_CRT macro. Using _ATL_MIN_CRT does not mean that
you cannot use the CRT routines. However, if you use the
routines that require the CRT startup code, then you will
get a linker error that _main is unresolved. Providing your
own implementation of _main does not solve this problem.
If C++ exceptions (/GX) are enabled, then you must link in
the startup code. The _ATL_MIN_CRT macro cannot be used in
this case. MFC requires code to be compiled with the /GX
option. Therefore, you cannot use _ATL_MIN_CRT in
conjunction with MFC. You can use SEH (structured exception
handling), __try, and __except with _ATL_MIN_CRT, because
the startup code is not required. In many cases, since most
of the CRT source code ships with the product, you can use
some of this code and replace only parts of it with system
calls to avoid the startup code.
To find out what is causing the problem, do one of the
following: • Open the Project Settings dialog box, select
the Link tab, and click Input in the Category box. Type
LIBCMT.LIB in the Ignore libraries text box. Now do a
build. You will get a list of unresolved externals. This
list contains the CRT routines you are using. Look for the
routines that you think may require the startup code.
• Turn on the /VERBOSE linker option. From the resulting
linker output, you can find a list of routines that require
the CRT startup code.
If you need the startup code, then remove the _ATL_MIN_CRT
definition from the Project Settings. You can also
dynamically link to CRT. This reduces your image size but
When building as Release, the default option is to
statically link to CRT and use _ATL_MIN_CRT. This gives a
smaller image size than dynamically linking to CRT, at
least when the startup code is avoided and the CRT APIs
used by AppWizard are used.