DEV Community

Yunus Emre Güzel
Yunus Emre Güzel

Posted on Originally published at blog.emreguzel.ca

gcc: Undefined Reference to WinMain (Fix on Windows)

Cause 4: Two Files Both Have a main

// a.c
int main(void) { return 0; }

// b.c
int main(void) { return 1; }
Enter fullscreen mode Exit fullscreen mode

A program can only have one main. If two files in the build both define it, the linker stops with a different message:

two_b.c:(.text+0x0): multiple definition of `main'; two_a.c:(.text+0x0): first defined here
Enter fullscreen mode Exit fullscreen mode

This often happens by accident when your editor's build task compiles every .c file in the folder. The task in my own repo does exactly that (gcc ${fileDirname}\*.c), so two experiments sitting in the same folder clash. A task that compiles only the file you have open causes the opposite problem, the one in the section above. Look at what your build task really runs, and either keep one program per folder or run gcc yourself with the exact files you want.

How to Read a Linker Message

Take a message like main.c:(.text+0xe3): undefined reference totasklist_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 afterundefined 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 firstundefined referenceormultiple definition`.

If you see many undefined references for different functions, check whether they all belong to one file. When I compiled only main.c of the task manager from How to Build Real-World Projects in C, one missing tasks.c produced a separate error for every function in it. That is one missing file, not many bugs.

Compile Error or Link Error?

The wording of the message tells you which step failed, 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

If gcc on Windows says undefined reference to 'WinMain', your program has no function named main that the linker can find. Check the spelling and capital letters of main, make sure it is defined with a body, and make sure the file that holds it is part of your gcc command. The message mentions WinMain only because that is the entry point Windows programs fall back to when main is missing.

plaintext
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
`

The long path in the first line is just the location of gcc's own startup code. The part that matters is 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 has two steps. The compiler turns each .c file into an object file, and then the linker joins the object files into a program. Every program needs one entry point, the function the operating system starts. On Windows with MinGW gcc, programs can start from main or from the Windows-style entry point WinMain. When you define neither, the linker's report names WinMain, which is the message I got every time main was missing or misnamed. I did not dig into gcc's startup code to confirm exactly why, so treat the name as a sign that no entry point was found.

This also tells you something useful. The error comes from the linker (ld), not from the compiler, so your code has no syntax problem. The file even compiles on its own when you stop before linking:

gcc -c nomain.c -o nomain.o
Enter fullscreen mode Exit fullscreen mode

That command succeeds with no output, and the error only appears when gcc tries to make a program out of it.

Cause 1: The File Has No main at All

This happens when you build a file that only holds helper functions, or when you started a file and forgot the entry point:

#include <stdio.h>

void hello(void) {
    printf("hello\n");
}
Enter fullscreen mode Exit fullscreen mode

Building it with gcc nomain.c -o nomain.exe gives the WinMain error above. The fix is to add a main that calls the function:

#include <stdio.h>

void hello(void) {
    printf("hello\n");
}

int main(void) {
    hello();
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Cause 2: main Is Misspelled or Has the Wrong Capital

C is case sensitive, so Main and mian are different functions from main. Both of these built to the same WinMain error on my machine:

#include <stdio.h>

int mian(void) {      /* typo: mian */
    printf("hello\n");
    return 0;
}
Enter fullscreen mode Exit fullscreen mode
#include <stdio.h>

int Main(void) {      /* capital M */
    printf("hello\n");
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

The compiler does not complain here, because mian and Main are perfectly good function names. Only the linker notices that nothing is called main. Rename the function to a lowercase main and it builds and prints hello.

Cause 3: You Are Building the Wrong File

In a project with several files, main lives in one of them. If your command names only a helper file, the linker finds no entry point. This helper file has no main:

#include <stdio.h>

void greet(void) {
    printf("hi from helper\n");
}
Enter fullscreen mode Exit fullscreen mode

Running gcc helper.c -o helper.exe fails with the WinMain message. Build the file that has main and name it in the command, as shown in the next section.

Related Error: undefined reference to Your Own Function

If the name in the message is one of your own functions instead of WinMain, you have the opposite problem. main exists, but a function it calls is defined in a file you did not give to gcc. Here app.c calls greet, which lives in helper.c:

void greet(void);

int main(void) {
    greet();
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Building only app.c fails with undefined reference togreet'`. List both files and it works:

bash
gcc app.c helper.c -o app.exe
./app.exe

plaintext
hi from helper

This differs from the implicit declaration of function error, which comes from the compiler when it has not seen a declaration. An undefined reference means the declaration is fine and the linker cannot find the function body.

How to Tell Which Cause You Have

  • Read the name after undefined reference to. WinMain means no usable main. Any other name means a function body is missing from the build.

  • Search your file for main. Check it is lowercase, spelled right, and has a body in braces.

  • Look at your gcc command. Does it name every .c file the program needs, including the one with main?

  • If you build from an editor, make sure it is compiling the file you are looking at and not an older one.

Build With Warnings On

Use gcc -Wall -Wextra every time, as in the garbage value guide. It will not catch a misspelled main, but it catches many other mistakes before they reach the linker. If your program now builds but skips input, see why your C program skips the second scanf, and if you are just starting out, the Introduction to C programming guide covers main and compiling from the beginning.

The Checklist

  • The program has exactly one function named main, all lowercase, with a body.

  • Your gcc command lists every .c file the program needs.

  • The file with main is one of them.

  • WinMain in the error means the entry point is missing. Another name means a function body is missing.

  • The error comes from the linker, so fix the build and the names, not your syntax.

The linker is only telling you it cannot find a starting point. Name main correctly, build the right files together, and the error goes away.

Download the code: broken and fixed versions of these cases are on GitHub in C-Programing/Troubleshooting/undefined-reference: no main, a misspelled main, a two-file project, and two main functions. Compile one file at a time, and use gcc main.c greet.c for the two-file example. If your program builds 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)