This error occurs when the linker can’t find WinMain
function, so it is probably missing. In your case, you are probably missing main
too.
Consider the following Windows API-level program:
#define NOMINMAX
#include <windows.h>
int main()
{
MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
Now let’s build it using GNU toolchain (i.e. g++), no special options. Here gnuc
is just a batch file that I use for that. It only supplies options to make g++ more standard:
C:test> gnuc x.cpp C:test> objdump -x a.exe | findstr /i "^subsystem" Subsystem 00000003 (Windows CUI) C:test> _
This means that the linker by default produced a console subsystem executable. The subsystem value in the file header tells Windows what services the program requires. In this case, with console system, that the program requires a console window.
This also causes the command interpreter to wait for the program to complete.
Now let’s build it with GUI subsystem, which just means that the program does not require a console window:
C:test> gnuc x.cpp -mwindows C:test> objdump -x a.exe | findstr /i "^subsystem" Subsystem 00000002 (Windows GUI) C:test> _
Hopefully that’s OK so far, although the -mwindows
flag is just semi-documented.
Building without that semi-documented flag one would have to more specifically tell the linker which subsystem value one desires, and some Windows API import libraries will then in general have to be specified explicitly:
C:test> gnuc x.cpp -Wl,-subsystem,windows C:test> objdump -x a.exe | findstr /i "^subsystem" Subsystem 00000002 (Windows GUI) C:test> _
That worked fine, with the GNU toolchain.
But what about the Microsoft toolchain, i.e. Visual C++?
Well, building as a console subsystem executable works fine:
C:test> msvc x.cpp user32.lib x.cpp C:test> dumpbin /headers x.exe | find /i "subsystem" | find /i "Windows" 3 subsystem (Windows CUI) C:test> _
However, with Microsoft’s toolchain building as GUI subsystem does not work by default:
C:test> msvc x.cpp user32.lib /link /subsystem:windows x.cpp LIBCMT.lib(wincrt0.obj) : error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartu p x.exe : fatal error LNK1120: 1 unresolved externals C:test> _
Technically this is because Microsoft’s linker is non-standard by default for GUI subsystem. By default, when the subsystem is GUI, then Microsoft’s linker uses a runtime library entry point, the function where the machine code execution starts, called winMainCRTStartup
, that calls Microsoft’s non-standard WinMain
instead of standard main
.
No big deal to fix that, though.
All you have to do is to tell Microsoft’s linker which entry point to use, namely mainCRTStartup
, which calls standard main
:
C:test> msvc x.cpp user32.lib /link /subsystem:windows /entry:mainCRTStartup x.cpp C:test> dumpbin /headers x.exe | find /i "subsystem" | find /i "Windows" 2 subsystem (Windows GUI) C:test> _
No problem, but very tedious. And so arcane and hidden that most Windows programmers, who mostly only use Microsoft’s non-standard-by-default tools, do not even know about it, and mistakenly think that a Windows GUI subsystem program “must” have non-standard WinMain
instead of standard main
. In passing, with C++0x Microsoft will have a problem with this, since the compiler must then advertize whether it’s free-standing or hosted (when hosted it must support standard main
).
Anyway, that’s the reason why g++ can complain about WinMain
missing: it’s a silly non-standard startup function that Microsoft’s tools require by default for GUI subsystem programs.
But as you can see above, g++ has no problem with standard main
even for a GUI subsystem program.
So what could be the problem?
Well, you are probably missing a main
. And you probably have no (proper) WinMain
either! And then g++, after having searched for main
(no such), and for Microsoft’s non-standard WinMain
(no such), reports that the latter is missing.
Testing with an empty source:
C:test> type nul >y.cpp C:test> gnuc y.cpp -mwindows c:/program files/mingw/bin/../lib/gcc/mingw32/4.4.1/../../../libmingw32.a(main.o):main.c:(.text+0xd2): undefined referen ce to `WinMain@16' collect2: ld returned 1 exit status C:test> _
Undefined reference to winmain@16′ occurs when there is a compilation error when you are working with C and C++ programming languages. If you are here because you want to learn how to fix this error, we’ll not disappoint you.
That’s because our experts analyzed this error and concluded that it’s best to list all possible causes and teach you how to fix each one. Now, grab your computer; launch your code editor; by the end of this article, you’ll have a working solution.
Why Your Code Has an Undefined Reference to Winmain@16’
Your code has an undefined reference to winmain@16 because of the following:
- You did not save your file
- Your code does not have the “main()” function
- There is a capital letter in “main()”
- You are using the Code::Blocks IDE
– You Did Not Save Your File
When you have a new source code in C or C++, if you don’t save it before compiling, an undefined reference to winmain@16 will occur. That’s because, at that time, you’ve not written the file to your disk, so your compiler considers it as an empty source file.
Besides, all compilers will not compile an empty source file, and they’ll produce an error as a sign of this. What’s more, at the start of the compilation, your compiler will check if you have the correct code.
One of these checks ensures your code has the “main()” function. But, without saving your file, there is no way for your compiler to know this so that it will produce an error.
– Your Code Does Not Have the “Main()” Function
Undefined reference to winmain@16′ MinGW error occurs because your code does not have the “main()” function. Your compiler considers the “main()” function as the entry point of your application.
Without it, the compilation process will stop, and you’ll have to fix your code. For example, have a look at the next recursion program written in the C programming language.
When you do a quick scan of the code, you’ll conclude that it should work because there is no syntax error. However, it will not because the code lacks a “main()” function that’ll serve as the entry point.
#include <stdlib.h>
// This program will not run because
// it has no main() function.
void print_num (int start)
{
printf( “%d”, start );
if ( start < 9 ) {
print_num (start + 1);
}
printf(“%d”, start);
}
If you compile the code above, take a look at your compiler logs, and you’ll notice the following, among other things:
Undefined reference to `winmain@16′ collect2.exe: error: ld returned 1 exit status
From the error message above, the part that says “winmain@16” is a sign that your code does don’t have the “main()” function. The ending part of the error showed “collect2.exe” returned an exit status.
This is another sign that you don’t have “main()” in your code because “collect2.exe” will generate a table that “main()” depends on. Without that table, the compiler will stop the compilation process and produce an error.
– There Is a Capital Letter in “Main()”
An undefined reference to winmain@16′ in C programming will occur if you have capital letters in the name of the “main()” function. By design, the function name consists of lowercase letters, and that’s what the compiler will look for in your code.
A capital letter might sneak into the name without you knowing, and it can happen if you type very fast. In the following, the code will not compile because we’ve spelled the function “main()” as “maIn()”; the latter has a capital “I” instead of the lowercase “i”:
// There is a capital letter in the name
// of the function “main()”. As a result,
// the compiler will not compile this code
int maIn() { // Note the capital letter “I”
printf(“Hello, Welcome to the C programming language”);
return 0;
}
– You Are Using the Code::Blocks Ide
Undefined reference to winmain CodeBlocks IDE error will occur due to the configuration or the behavior of the IDE itself. CodeBlocks (or Code::Blocks) has a reputation for failing to compile a code after a while, even if the code has no errors.
This happens when Code::Blocks fails to link the header C++ files to your project in the correct way. Although it can ask you to link them when you create them, still, this does not mean that you won’t see the error.
Another cause of the error is when you don’t update the “Build options” settings of Code::Blocks. That’s because you need to enable some settings before Code::Blocks can work correctly with your files. Not only that, when you start creating “classes” in your code, you must activate a setting. Without this setting, the possibility of compilation error increases.
You can fix the undefined reference to winmain@16 using any of the following solutions:
- Always save your file before compiling your code
- Ensure your code has the “main()” function
- Avoid capital letters in the name of “main()”
- Restart Code::Blocks or update its build options
1. Always Save Your File Before Compiling Your Code
A solution to the undefined reference to winmain@16′ VSCode error is to save your new source file before you compile it. Mind you; this is not specific to VS Code alone; it’s the same for other IDE. But, we’ll focus on VS Code because it’s popular, and if you are reading this article, we guess you have it installed.
Now, the following are two ways to save your file in VS Code to prevent the winmain@16 error:
- Use the Ctrl key and “S” key on your keyboard (Command key and “S” on macOS).
- Configure auto-save before compilation.
The first one applies to other IDE, but the second applies to VS Code. When you configure auto-save in VS Code, you don’t need to use the keyboard shortcut to save your file.
To configure auto-save in VS Code, do the following:
- Click on the “Manage” icon in the bottom-left corner of the application window.
- Click on “Settings” from the menu.
- Search for “Save” using the search bar.
- Scroll down until you find the following checkboxes:
- “Save All Files Before Run”
- “Save File Before Run”
- Click on both checkboxes, and close the setting window.
Now, every time you compile a new source file, VS Code will auto-save it before it compiles it. As a result, you’ll no longer see the error when you want to compile your C or C++ source code.
2. Ensure Your Code Has the “Main()” Function
A major fix for the undefined reference to winmain MinGW-w64 error is the “main()” function. Earlier in this article, we showed you a piece of code that lacked the “main()” function. As a result, you’ll get an error when you compile it; once again, here is the code:
#include <stdlib.h>
// This program will not run because
// it has no main() function.
void print_num (int start)
{
printf( “%d”, start );
if ( start < 9 ) {
print_num (start + 1);
}
printf(“%d”, start);
}
If we rewrite it to the following, you’ll no longer get the error because the code now has a “main()” function.
#include <stdio.h>
#include <stdlib.h>
void print_num (int start)
{
printf( “%d”, start );
if ( start < 9 ) {
print_num (start + 1);
}
printf(“%d”, start);
}// A quick fix is to add the main() function// before calling the print_num function. With this, the// compiler will not complain about an undefined// reference to winmain.int main() {
print_num(7);
}
3. Avoid Capital Letters in the Name of “Main()”
If you don’t put capital letters in the name of the “main()” function, you can stop the winmain@16 error. That’s because “main()” is case-sensitive, and it contains all lowercase letters; it’s not “maiN()” nor “Main()”. We say this because It’s easy to include a capital letter without you knowing.
The following are preventive measures that’ll stop this:
- Don’t use a font that makes it difficult to differentiate capital and small letters in your code editor.
- Search your IDE shortcut menu; if it has a shortcut to include the “main()” function, always use it.
- Create an empty definition of the “main()” function and store it in a file. By doing this, you can copy it to your current project when you need it.
Based on the code that had an “I” in function “main()”, the following is a rewrite that does not contain an error:
// Your compiler will run this and show
// “Hello, welcome to the C programming language!”
int main() {
printf(“Hello, welcome to the C programming language!”);
return 0;
}
4. Restart Code::Blocks or Update Its Build Options
Restarting Code::blocks is a sure way to fix undefined reference to `winmain@16′ GCC error. By doing this, you can start all over again, but this time, you can compile your code without errors.
So, the next time you encounter the winmain@16 error in CodeBlocks, always restart your code. Another option is to update the “Build options” in CodeBlocks using the following:
- Click on “Settings” at the top menu bar.
- Select “Compiler” from the dropdown menu.
- Click on the “Build options” tab (if you have a small screen, scroll to the right).
- Select the checkbox that reads “Explicitly add currently compiling file’s directory to compiler search dirs.”
Both solutions will work, and you’ll not face the winmain@16 error in the future. But, ensure you always write correct code that conforms to the syntax of C and C++.
Conclusion
In this article, we discussed the causes of an undefined reference to winmain@16 in C and C++. Not only that, we explained how you could fix it depending on your situation. Now, we leave you with the following talking points from our discussion:
- If you don’t save your new source file, it will cause an undefined reference to winmain@16.
- If your code does not have the “main()” you’ll get an error during compilation.
- You can set up auto-save in VS Code to prevent undefined references to winmain@16.
- An update of “Build options” in CodeBlocks will prevent the undefined reference to winmain@16.
At this stage, you have everything you need to solve the winmain error in your C and C++ programming projects.
- Author
- Recent Posts
Position Is Everything: Your Go-To Resource for Learn & Build: CSS,JavaScript,HTML,PHP,C++ and MYSQL.
Introduction
In this article I’ll be looking at the “undefined reference” error message (or “unresolved external symbol, for Visual C++ users). This is not actually a message from the compiler, but is emitted by the linker, so the first thing to do is to understand what the linker is, and what it does.
Linker 101
To understand the linker, you have to understand how C++ programs are built. For all but the very simplest programs, the program is composed of multiple C++ source files (also known as “translation units”). These are compiled separately, using the C++ compiler, to produce object code files (files with a .o or a .obj extension) which contain machine code. Each object code file knows nothing about the others, so if you call a function from one object file that exists in another, the compiler cannot provide the address of the called function.
This is where the the linker comes in. Once all the object files have been produced, the linker looks at them and works out what the final addresses of functions in the executable will be. It then patches up the addresses the compiler could not provide. It does the same for any libraries (.a and .lib files) you may be using. And finally it writes the executable file out to disk.
The linker is normally a separate program from the compiler (for example, the GCC linker is called ld) but will normally be called for you when you use your compiler suite’s driver program (so the GCC driver g++ will call ld for you).
Traditionally, linker technology has lagged behind compilers, mostly because it’s generally more fun to build a compiler than to build a linker. And linkers do not necessarily have access to the source code for the object files they are linking. Put together, you get a situation where linker errors, and the reasons for them, can be cryptic in the extreme.
Undefined reference
Put simply, the “undefined reference” error means you have a reference (nothing to do with the C++ reference type) to a name (function, variable, constant etc.) in your program that the linker cannot find a definition for when it looks through all the object files and libraries that make up your project. There are any number of reasons why it can’t find the definition – we’ll look at the commonest ones now.
No Definition
Probably the most common reason for unresolved reference errors is that you simply have not defined the thing you are referencing. This code illustrates the problem:
int foo(); int main() { foo(); }
Here, we have a declaration of the function foo(), which we call in main(), but no definition. So we get the error (slightly edited for clarity):
a.cpp:(.text+0xc): undefined reference to `foo()' error: ld returned 1 exit status
The way to fix it is to provide the definition:
int foo(); int main() { foo(); } int foo() { return 42; }
Wrong Definition
Another common error is to provide a definition that does not match up with declaration (or vice versa). For example, if the code above we had provided a definition of foo() that looked like this:
int foo(int n) { return n; }
then we would still get an error from the linker because the signatures (name, plus parameter list types) of the declaration and definition don’t match, so the definition actually defines a completely different function from the one in the declaration. To avoid this problem, take some care when writing declarations and definitions, and remember that things like references, pointers and const all count towards making a function signature unique.
Didn’t Link Object File
This is another common problem. Suppose you have two C++ source files:
// f1.cpp int foo(); int main() { foo(); }
and:
// f2.cpp int foo() { return 42; }
If you compile f1.cpp on its own you get this:
f1.cpp:(.text+0xc): undefined reference to `foo()'
and if you compile f2.cpp on its own, you get this even more frightening one:
crt0_c.c:(.text.startup+0x39): undefined reference to `WinMain@16
In this situation, you need to compile both the the source files on the same command line, for example, using GCC:
$ g++ f1.cpp f2.cpp -o myprog
or if you have compiled them separately down to object files:
$ g++ f1.o f2.o -o myprog
For further information on compiling and linking multiple files in C++, particularly with GCC, please see my series of three blog articles starting here.
Wrong Project Type
The linker error regarding WinMain above can occur in a number of situations, particularly when you are using a C++ IDE such as CodeBlocks or Visual Studio. These IDEs offer you a number of project types such as “Windows Application” and “Console Application”. If you want to write a program that has a int main() function in it, always make sure that you choose “Console Application”, otherwise the IDE may configure the linker to expect to find a WinMain() function instead.
No Library
To understand this issue, remember that a header file (.h) is not a library. The linker neither knows nor cares about header files – it cares about .a and .lib files. So if you get a linker error regarding a name that is in a library you are using, it is almost certainly because you have not linked with that library. To perform the linkage, if you are using an IDE you can normally simply add the library to your project, if using the command line, once again please see my series of blog articles on the GCC command line starting here, which describes some other linker issues you may have.
Conclusion
The unresolved reference error can have many causes, far from all of which have been described here. But it’s not magic – like all errors it means that you have done something wrong, in you code and/or your project’s configuration, and you need to take some time to sit down, think logically, and figure out what.
Code:Blocks forum,
Here’s the information I left out in my original post.
I am running Code::Blocks version 16.01 on Windows 7 Professional SP1
The compiler I use is Mingw32 and search directories set to
C:SDL2-2.0.5includeSDL. There are no relative paths in my setup.
When I build a simple «Hello World» program there are no errors and
it runs successfully. If I add #include <SDH.h> and try to build it
again I get the error message ‘undefined reference to ‘WinMain@16’
File name is main.cpp
#include <SDL.h>
#include <iostream>
using namespace std;
int main()
{
cout << «Hello world!» << endl;
return 0;
}
BUILD LOG WITHOUT #include <SDL.h>
————— Build: Debug in SDL (compiler: GNU GCC Compiler)—————
mingw32-g++.exe -Wall -std=c++11 -fexceptions -g -mwindows -std=c++11 -mwindows -IC:SDL2-2.0.5includeSDL2 -I»C:Program FilesCodeBlocksSDL» -IC:SDL2-2.0.5includeSDL2 -I»C:Program FilesCodeBlocksSDL» -c «C:Program FilesCodeBlocksSDLmain.cpp» -o objDebugmain.o
mingw32-g++.exe -LC:SDL2-2.0.5lib -LC:SDL2-2.0.5lib -o binDebugSDL.exe objDebugmain.o -lmingw32 -lSDL2main -lSDL2 -lmingw32 -lSDL2main -lSDL2
Output file is binDebugSDL.exe with size 1.01 MB
Process terminated with status 0 (0 minute(s), 0 second(s))
0 error(s), 0 warning(s) (0 minute(s), 0 second(s))
BUILD LOG WITH #include <SDL.h>
————— Build: Debug in SDL (compiler: GNU GCC Compiler)—————
mingw32-g++.exe -Wall -std=c++11 -fexceptions -g -mwindows -std=c++11 -mwindows -IC:SDL2-2.0.5includeSDL2 -I»C:Program FilesCodeBlocksSDL» -IC:SDL2-2.0.5includeSDL2 -I»C:Program FilesCodeBlocksSDL» -c «C:Program FilesCodeBlocksSDLmain.cpp» -o objDebugmain.o
mingw32-g++.exe -LC:SDL2-2.0.5lib -LC:SDL2-2.0.5lib -o binDebugSDL.exe objDebugmain.o -lmingw32 -lSDL2main -lSDL2 -lmingw32 -lSDL2main -lSDL2
C:/Program Files (x86)/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/4.9.2/../../../libmingw32.a(main.o):main.c:(.text.startup+0xa7): undefined reference to `WinMain@16′
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minute(s), 0 second(s))
2 error(s), 0 warning(s) (0 minute(s), 0 second(s))
OTHER THINGS I HAVE TRIED
There was a suggestions on the web regarding placing -mwindows as compiler
flag which you can see in the Build logs.
Select the checkbox in Settings-> Compiler > Build options «Explicitly add currently compiling file’s directory to compiler search dirs».
Closing and reopening Code:Blocks.
Go to project > build option and put a check mark on «Have g++ follow the C++11 ISO C++ language standard [-std=c++11]».
project —> build option Put check mark on » Have g++ follow the C++11 ISO C++ language standard [-std=c++11]»
Any suggestions?
Jerry D.