Identify the failing build stage
In C and C++, an undefined reference usually means the linker could not find a required definition before the program started. Syntax-correct sources can still fail when object files and libraries are combined into an executable. Check that the latest build actually succeeded. An older executable may remain in the output directory after a failed build, making it seem that the new source is running. Distinguish the last successful artifact from the output of the current attempt.
A declaration is not a linked definition
A function declaration in a header does not ensure that its implementation is present in the link. Check that the implementing source file belongs to the target and defines the exact expected symbol. In C++, namespaces, argument types, and qualifiers can distinguish symbols that look similar in casual reading. Template definitions and required instantiations introduce additional considerations. Read the full symbol in the linker message rather than a shortened name. The question is whether that exact definition was produced and supplied.
Inspect the actual link command
Using an external header also requires the appropriate library implementation. Compilation can succeed after finding the header while linking fails because its library is absent. Verify library architecture and toolchain compatibility. Some linking arrangements also depend on library order. Look at the complete command emitted by the build system and map each required symbol to the input expected to provide it. Add a missing input for a clear reason rather than collecting unrelated options from search results. Treat a different subsequent message as new evidence.
Debug only the new successful artifact
After correcting the link, verify that a new executable exists and reopen that file in DBG Desk. Otherwise the session may still inspect the previous version. A useful small reproduction contains the declaration, definition, caller, and complete build command. For a link problem, compiler and linker output and configuration are more useful than runtime logs. Separating build failures from execution failures quickly narrows the appropriate tools and information.
A two-file example
Suppose main.c calls helper and helper.c defines it. Linking only main.c omits the implementation even when both files are visible in the project folder. Building both establishes whether that omission explains the failure. With a build system, verify that helper’s object appears in the actual link inputs. File presence and target membership are different facts.
gcc -g -O0 main.c helper.c -o example.exe