-1

i'm trying to create a simple windows application but based on a main() entry point since i need to compile it on other platforms.

I found specific directives to do this with visual studio but it seems to work when using /MD runtime library compilation, but crashes when using /MT.

Here is a complete code to reproduce the crash, it fails every time. ==> Just create an empty project with a main.cpp file and set : Projet -> Properties -> C/C++ -> Code Generation -> Runtime Library -> /MT

#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
#pragma comment(linker, "/ENTRY:main")
#pragma comment(linker, "/INCLUDE:mainCRTStartup")

int main(int argc, char** argv)
{

    int* a = new int;
    delete a;

    return 0;
}

This causes the following exception :

ntdll.dll!RtlpWaitOnCriticalSection()   Inconnu
ntdll.dll!RtlpEnterCriticalSectionContended()   Inconnu
ntdll.dll!RtlEnterCriticalSection() Inconnu
Application.exe!__acrt_lock(__acrt_lock_id _Lock) Ligne 55  C++
Application.exe!heap_alloc_dbg_internal(const unsigned __int64 size, const int block_use, const char * const file_name, const int line_number) Ligne 309    C++
Application.exe!heap_alloc_dbg(const unsigned __int64 size, const int block_use, const char * const file_name, const int line_number) Ligne 450 C++
Application.exe!_malloc_dbg(unsigned __int64 size, int block_use, const char * file_name, int line_number) Ligne 496    C++
Application.exe!malloc(unsigned __int64 size) Ligne 27  C++
[Code externe]  
Application.exe!main(int argc, char * * argv) Ligne 9   C++
[Code externe]  

But if i use a WinMain entry point, it won't fail :

#pragma comment(linker, "/SUBSYSTEM:WINDOWS")

int main(int argc, char** argv)
{

    int* a = new int;
    delete a;

    return 0;
}

INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
{
    return main(1, reinterpret_cast<char**>(&lpCmdLine));
}

I want to complile without MSVCRT external dependency, this is the reason why i'm setting /MT mode.

Do you have any suggestion ? I'm working on this problem for days actually....

Kazuya
  • 65
  • 3
  • You could just use #ifdef to switch between main and winmain depending on the OS. – Dave S Apr 28 '19 at 17:41
  • `#pragma comment(linker, "/SUBSYSTEM:WINDOWS")` - You are doing it wrong. You should get your build system to ensure the right flags are passed to the compiler/linker. *Don't* put that into source files. This is also *horribly non-portable*. – Jesper Juhl Apr 28 '19 at 17:45
  • 1
    This post looks to be trying to do two very different things: build a windows program with no dependency on the VC runtime vs. build a Windows program that uses the same `main` as other platforms. Which *specifically* are you trying to accomplish, and if the latter, why are you trying to accomplish it with the former. Or did I miss something (wouldn't be the first time). – WhozCraig Apr 28 '19 at 17:46

2 Answers2

1

The entry point is not main or WinMain, it is a function in the MS libraries that will initialize the CRT. You main example does not work because you bypass that initialization. The WinMain example works because this initialization occurs before WinMain starts execution. When linking to the DLL version of the runtime, this initialization happens when the DLL is loaded.

You should specify /SUBSYSTEM:CONSOLE, or just leave it off and let the linker figure out the proper subsystem.

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
  • The problem with the /SUBSYSTEM:CONSOLE is that i can see the console appearing, even if i Hide it with FreeConsole or any other way, the console will appear for an instant. I know what i want to do is possible because some projects can do this with CMAKE, but i can't reproduce the cmake configuration with a project creation. Here's an example : https://github.com/GameTechDev/IntroductionToVulkan/blob/master/Project/Tutorials/02/main.cpp – Kazuya Apr 28 '19 at 18:13
0

Put the linker option to CONSOLE (more info here) and that's all. If you don't want the console, detach from it using FreeConsole.

The other easy solution is to have WinMain call a custom main2 when on Windows and to have main call the same main2 on other platforms.

#ifdef _WIN32
int __stdcall WinMain(...) { return main2(); }
#else
int main(...) { return main2(); }
#endif
Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78