Cause 4: Two Files Both Have a main
// a.c
int main(void) { return 0; }
// b.c
int main(void) { return 1; }
You get one main per program. Put it in two files and the linker bails out with a different message:
two_b.c:(.text+0x0): multiple definition of `main'; two_a.c:(.text+0x0): first defined here
It usually happens by accident. Your editor's build task compiles every .c file in the folder, so two experiments side by side clash. The task in my own repo does exactly that (gcc ${fileDirname}\*.c). A task that builds only the open file gives you the opposite problem, the one in the section above. So check what your build task really runs. Then keep one program per folder, or call gcc yourself with the exact files you want.
How to Read a Linker Message
Take a message like main.c:(.text+0xe3): undefined reference to `tasklist_init’. The file name tells you which file asked for the function, and (.text+0xe3) is a position inside the compiled code that you can ignore. The part that matters is the name after undefined reference to. The last line, collect2.exe: error: ld returned 1 exit status, only says that the linker failed, so the useful information is always in the lines above it. Scroll up and read the first undefined reference or multiple definition.
Seeing lots of undefined references for different functions? Check whether they all live in one file. I compiled only main.c of the task manager from How to Build Real-World Projects in C. One missing tasks.c gave me a separate error for every function in it. That's one missing file, not a pile of bugs.
Compile Error or Link Error?
The wording tells you which step broke, and that tells you where to look:
| Message | Step | Look at |
|---|---|---|
implicit declaration of function |
Compiler | Missing #include, a typo, or a function used before it is declared. See C Error: Implicit Declaration of Function. |
undefined reference to a function you wrote |
Linker | A .c file missing from the gcc command |
undefined reference to WinMain (or main) |
Linker | No main, or main misspelled |
multiple definition of |
Linker | The same function defined in two files |
The Short Answer
Gcc on Windows says undefined reference to 'WinMain'? Then the linker can't find a function called main in your program. Check the spelling and the capital letters. Make sure main has a body. Make sure the file that holds it is in your gcc command. Why does the message say WinMain? Because that's the entry point Windows programs fall back to when main is missing.
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/16.2.0/../../../../lib/libmingw32.a(lib64_libmingw32_a-crtexewin.o):crtexewin.c:(.text.startup+0xc6): undefined reference to `WinMain'
collect2.exe: error: ld returned 1 exit status
Don't worry about the long path on the first line. It's just where gcc keeps its own startup code. Look at the end: undefined reference to `WinMain'. Everything below shows the causes I could reproduce with gcc 16.2 from MSYS2 on Windows, in the order you are most likely to meet them. If you use a different compiler setup, the wording may differ (some setups name main instead), but the causes are the same.
Why You See WinMain and Not main
Building a C program takes two steps. First the compiler turns each .c file into an object file. Then the linker glues the object files into a program. Every program needs one entry point, which is the function the operating system starts. With MinGW gcc on Windows, a program can start from main or from the Windows-style WinMain. Define neither and the linker names WinMain. That's what I got every time main was missing or misnamed. I didn't dig into gcc's startup code to confirm why, so read the name as a sign that no entry point was found.
This also tells you something handy. The error comes from the linker (ld), not the compiler. So your syntax is fine. The file even compiles on its own if you stop before linking:
gcc -c nomain.c -o nomain.o
That command works and prints nothing. The error shows up only when gcc tries to build a program from it.
Cause 1: The File Has No main at All
You'll hit this when you build a file that holds only helper functions. Or when you started a file and forgot the entry point:
#include <stdio.h>
void hello(void) {
printf("hello\n");
}
Build it with gcc nomain.c -o nomain.exe and you get the WinMain error above. Add a main that calls the function and you're done:
#include <stdio.h>
void hello(void) {
printf("hello\n");
}
int main(void) {
hello();
return 0;
}
Cause 2: main Is Misspelled or Has the Wrong Capital
C cares about case. Main and mian aren't main, they're other functions. Both of these gave me the same WinMain error on my machine:
#include <stdio.h>
int mian(void) { /* typo: mian */
printf("hello\n");
return 0;
}
#include <stdio.h>
int Main(void) { /* capital M */
printf("hello\n");
return 0;
}
The compiler stays quiet, since mian and Main are fine names for a function. Only the linker notices that nothing is called main. Rename it to a lowercase main. It builds and prints hello.
Cause 3: You Are Building the Wrong File
A project with several files keeps main in just one of them. Name only a helper file in your command and the linker has no entry point to find. This helper file has no main:
#include <stdio.h>
void greet(void) {
printf("hi from helper\n");
}
Run gcc helper.c -o helper.exe and you get the WinMain message. Build the file that has main instead, and name it in the command, as the next section shows.
Related Error: undefined reference to Your Own Function
Sometimes the name in the message is one of your own functions, not WinMain. That's the opposite problem. main is there, but a function it calls lives in a file you never gave to gcc. Here app.c calls greet, which is defined in helper.c:
void greet(void);
int main(void) {
greet();
return 0;
}
Build only app.c and it fails with undefined reference to `greet'. Give gcc both files and it works:
gcc app.c helper.c -o app.exe
./app.exe
hi from helper
Don't mix this up with the implicit declaration of function error. That one comes from the compiler, when it hasn't seen a declaration. Here the declaration is fine. The linker just can't find the function body.
How to Tell Which Cause You Have
Look at the name after
undefined reference to.WinMainmeans there's no usablemain. Any other name means a function body is missing from the build.Search your file for
main. Is it lowercase? Spelled right? Does it have a body in braces?Check your gcc command. Does it name every
.cfile the program needs, including the one withmain?Building from an editor? Make sure it compiles the file you're looking at, not an older one.
Build With Warnings On
Run gcc -Wall -Wextra every time, like in the garbage value guide. It won't flag a misspelled main. It does catch plenty of other mistakes before the linker sees them. Does your program build now but skip input? Read why your C program skips the second scanf. Just starting out? The Introduction to C programming guide covers main and compiling from the beginning.
The Checklist
Your program has exactly one function named
main, all lowercase, with a body.Your gcc command lists every
.cfile the program needs.The file with
mainis one of them.WinMainin the error means the entry point is missing. Any other name means a function body is missing.The linker raises this error, so fix the build and the names. Your syntax is fine.
The linker just can't find a place to start. Spell main right, build the right files together, and the error is gone.
Download the code: broken and fixed versions of these cases are on GitHub in C-Programing/Troubleshooting/undefined-reference. You get no main, a misspelled main, a two-file project, and two main functions. Compile one file at a time. For the two-file example, use gcc main.c greet.c. Builds fine but crashes? See Segmentation Fault in C: Find the Exact Line.
Originally published on my blog. I post new C, Python and AI-agent guides there regularly.
Top comments (0)