Question

This code compiles, but no surprises, it fails while linking (no main found):

Listing 1:

void main();

Link error: \mingw\lib\libmingw32.a(main.o):main.c:(.text+0x106) undefined reference to _WinMain@16'

But, the code below compiles and links fine, with a warning:

Listing 2:

void (*main)();

warning: 'main' is usually a function

Questions:

  1. In listing 1, linker should have complained for missing "main". Why is it looking for _WinMain@16?

  2. The executable generated from listing 2 simply crashes. What is the reason?

Thanks for your time.

Was it helpful?

Solution

Case 1. is Windows-specific - the compiler probably generates _WinMain symbol when main is properly defined.

Case 2. - you have a pointer, but as static variable it's initialized to zero, thus the crash.

OTHER TIPS

True, main doesn't need to be a function. This has been exploited in some obfuscated programs that contain binary program code in an array called main.

The return type of main() must be int (not void). If the linker is looking for WinMain, it thinks that you have a GUI application.

In most C compilation systems, there is no type information associated with symbols that are linked. You could declare main as e.g.:

char main[10];

and the linker would be perfectly happy. As you noted, the program would probably crash, uless you cleverly initialized the contents of the array.

Your first example doesn't define main, it just declares it, hence the linker error.

The second example defines main, but incorrectly.

On Windows platforms the program's main unit is WinMain if you don't set the program up as a console app. The "@16" means it is expecting 16 bytes of parameters. So the linker would be quite happy with you as long as you give it a function named WinMain with 16 bytes of parameters.

If you wanted a console app, this is your indication that you messed something up.

You declared a pointer-to-function named main, and the linker warned you that this wouldn't work.

The _WinMain message has to do with how Windows programs work. Below the level of the C runtime, a Windows executable has a WinMain.

Try redefining it as int main(int argc, char *argv[])

What you have is a linker error. The linker expects to find a function with that "signature" - not void with no parameters

See http://publications.gbdirect.co.uk/c_book/chapter10/arguments_to_main.html etc

In listing 1, you are saying "There's a main() defined elsewhere in my code --- I promise!". Which is why it compiles. But you are lying there, which is why the link fails. The reason you get the missing WinMain16 error, is because the standard libraries (for Microsoft compiler) contain a definition for main(), which calls WinMain(). In a Win32 program, you'd define WinMain() and the linker would use the library version of main() to call WinMain().

In Listing 2, you have a symbol called main defined, so both the compiler & the linker are happy, but the startup code will try to call the function that's at location "main", and discover that there's really not a function there, and crash.

1.) An (compiler/platform) dependent function is called before code in main is executed and hence your behavior(_init in case of linux/glibc).
2) The code crash in 2nd case is justified as the system is unable to access the contents of the symbol main as a function which actually is a function pointer pointing to arbitrary location.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top