3

I am compiling a DLL twice (once for x86, once for x64) and I have set /ENTRY to "DllMain". I am using the /MT runtime library option to statically link against the runtime library. This all work fine when doing the x86 build, but the x64 build fails with this:

error LNK2019: unresolved external symbol main referenced in function __tmainCRTStartup
{project directory}\LIBCMT.lib(crt0.obj)

Why does this work for the x86 build and not the x64 build? Is there something I am missing here?

Jon Tackabury
  • 47,710
  • 52
  • 130
  • 168
  • Why are you using /ENTRY? IIRC if you're using the standard DllMain() function the runtime calls it without any additional help. – Timo Geusch Sep 09 '10 at 22:42
  • If I specify /ENTRY in my x86 DLL the final size of the DLL is 5kb, if I don't set /ENTRY the final size is over 50kb. – Jon Tackabury Sep 09 '10 at 22:48
  • 2
    Normally the *real* entrypoint is taken by a "fake" DllMain provided by the CRT to initialize its internal data structures (as explained here: http://stackoverflow.com/questions/2674736/loading-a-dll-from-a-dll/2686042#2686042), so you're bypassing it. Probably the size reduction is due to CRT init code being removed. Your dll is working with a non-initialized CRT, which is very bad. – Matteo Italia Sep 09 '10 at 23:40
  • @Matteo: Very interesting, I had no idea. You should post this as an answer so I can accept it. :) – Jon Tackabury Sep 10 '10 at 01:43
  • Ok, I didn't post it before as an answer since it's not exactly an answer to your problem, but yet another problem that may arise at runtime. :) – Matteo Italia Sep 10 '10 at 08:46

2 Answers2

1

Not a direct answer but it may be strictly related: as said in the comment, you should avoid changing the entrypoint in that way: normally the real entrypoint is taken by a "fake" DllMain provided by the CRT to initialize its internal data structures (as explained here), so you're bypassing it. Probably the size reduction is due to CRT init code being removed.

Your dll is working with a non-initialized CRT, which is very bad. You should leave the default entrypoint, which, incidentally, should solve your problem.

By the way, notice that actually you could make a dll without the CRT (and it would become really small), but you shouldn't use the CRT at all, without even linking against it (/NODEFAULTLIB switch). This means that you could just use libraries you explicitly link against (e.g. the Windows API), but I suspect you would lose several C++ features (I think at least exceptions and RTTI).

Community
  • 1
  • 1
Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
0

This could be a silly question, but are you sure you're linking as a DLL in the x64 case (ie. specifying the /DLL switch) - since the complaint is about main, I wonder whether it's trying to link as a an executable?

RichieHindle
  • 272,464
  • 47
  • 358
  • 399
  • On the "General" tab, I have the configuration type set to "Dynamic Library (.dll)". Is this what you mean? – Jon Tackabury Sep 09 '10 at 22:46
  • That does sound right. You should compare the linker command lines of the two targets, via the Linker / Command Line page of the project settings. – RichieHindle Sep 09 '10 at 22:47
  • I have compared the command lines, and the only part that's different (apart from the output folders) is the /MACHINE option. – Jon Tackabury Sep 09 '10 at 22:50
  • @Jon: ...and be sure to check both the Debug and Release settings for both the x86 and x64 targets. That Project Properties dialog makes it very easy to omit one of those four places when setting things like the Configuration Type. – RichieHindle Sep 09 '10 at 22:51
  • I don't even have Debug settings any more, just Release. :) An interesting note, if I use /MD it works fine, but using /MT won't link. I really need to link this statically though to avoid distributing the C++ runtime DLLs. – Jon Tackabury Sep 09 '10 at 22:54