visual studio c++ LNK1120 error

May 11, 2008
22,604
1,473
126
RAAAAAAAAAAAAAHH !!!! :mad::mad::mad::mad:

I have had this error before and i was never able to solve it, because the error is not in my code.

Whenever this message pops up, i can stop with the project because i cannot get the error removed unless i decide to no longer use the windows function.

Is there a fix for this ?

It has happened to me before and it is annoying as hell, when my code generates no errors and warnings, yet the linker cannot resolve an error in a windows function. What am i doing wrong or what bug have i encountered here ? I have not seen this for over a year and now that i am almost finished(give or take a week of programing), it pops up.



Build started: Project: unicodetest, Configuration: William Release|Win32
Command Lines Creating temporary file "e: \My docs\Visual Studio 2008\Projects\unicodetest\unicodetest\William Release\RSP0000011168988.rsp" with contents
[
/Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Gm /EHsc /RTC1 /MDd /J /Fo"William Release\\" /Fd"William Release\vc90.pdb" /W3 /c /ZI /TP
]

...


Generating Code...
Compiling resources...
Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
Copyright (C) Microsoft Corporation. All rights reserved.
Compiling manifest to resources...
Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
Copyright (C) Microsoft Corporation. All rights reserved.
Linking...
LINK : E: \ My docs\Visual Studio 2008\Projects\unicodetest\William Release\unicodetest.exe not found or not built by the last incremental link; performing full link
main.obj : error LNK2019: unresolved external symbol "void __cdecl SetMainWindowMaxSize(struct HWND__ *,int,int)" (?SetMainWindowMaxSize@@YAXPAUHWND__@@HH@Z) referenced in function "long __stdcall WndProc(struct HWND__ *,unsigned int,unsigned int,long)" (?WndProc@@YGJPAUHWND__@@IIJ@Z)
E: \ My docs\Visual Studio 2008\Projects\unicodetest\William Release\unicodetest.exe : fatal error LNK1120: 1 unresolved externals
Results Build log was saved at "file://e: \My docs\Visual Studio 2008\Projects\unicodetest\unicodetest\William Release\BuildLog.htm"
unicodetest - 2 error(s), 0 warning(s)

I had to insert spaces into the paths to prevent generation of smileys.
 

Cogman

Lifer
Sep 19, 2000
10,286
147
106
SetMainWindowMaxSize is not a windows function. I don't know where you are pulling it from (google doesn't know either).

Your linker error is essentially saying "Hey, you reference this function but don't ever define it, I can't see it any of the libraries you are including either!"

If it is your own function, make sure the linker is compiling the file that contains that function (and that that file does indeed contain that function). You might have to do a rebuild all.
 
Last edited:
May 11, 2008
22,604
1,473
126
In this case, you are right. It was a custom function of my own. :D

I got confused because instead of Visual Studio mentioning that the function does not exist in the *.cpp file ( I deleted it by accident) i got all this nonsense that there was a calling convention error. The prototype was still present in the *.header file. Of course there was such an error, but it would have been more obvious if the compiler or the linker would have mentioned that the function does not exist and therefore has a calling problem.

I guess i am getting used by the clarity of the messages that i get when i use GNU GCC. Which is strange, because i use a GUI to use GNU GCC ( command line app).

As a sidenote and not related to the posted problem :
I feel it is similar as when programmers come up with fancy talk such as "references to objects". This just means in the situation wherein i was confronted with this : "pointers to variables".

:)

Almost forgot :

I found the issue after i posted the thread.
But i could not add a new post because anandtech forum took minutes to load for some reason.
 
Last edited:

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
I feel it is similar as when programmers come up with fancy talk such as "references to objects". This just means in the situation wherein i was confronted with this : "pointers to variables".

In an abstract sense you're right, but I think it's better to keep the idea of pointers and references separate. In some languages, like C++, they are different mechanisms with different behaviors. Others, like C#, don't have pointers, and everything is a reference. It might be best to keep "pointer to x" clearly defined as "address of x in memory," and "reference to x" clearly defined as "name through which x can be manipulated."
 

Cogman

Lifer
Sep 19, 2000
10,286
147
106
In this case, you are right. It was a custom function of my own. :D

I got confused because instead of Visual Studio mentioning that the function does not exist in the *.cpp file ( I deleted it by accident) i got all this nonsense that there was a calling convention error. The prototype was still present in the *.header file. Of course there was such an error, but it would have been more obvious if the compiler or the linker would have mentioned that the function does not exist and therefore has a calling problem.
In this case, there is no way for the linker to tell where the function actually is. By keeping the prototype in the file, you are telling the compiler "Hey, don't throw fits, I'm going to define this function later, somewhere else. Let the linker take care of it." To which it happily hums along and puts notes in the object code to tell the linker "Hey, the programmer says this references a function, I don't know where that function is, you'll have to find it.

The problem comes from the fact that the function could be defined almost anywhere. A library, another object file, wherever (ok... really those are about the only two.) so the linker can't just say "Well, you're missing a C++ file here" or "Well, your missing this library here." I simply sees a function that needs and address and in its bank of addresses that function does not exist.

The alternative would be to have the linker know everything about every library on the system, which would really increase compile times whenever a reference comes up where a definition doesn't exist.

Whats worse, libraries may have the same function signatures. With the programmer telling the linker "I want to use the function from this library or this object file" having it guess could be disastrous.
 
May 11, 2008
22,604
1,473
126
Well, i can accept that. But it would have been nice if the linker or the compiler just would have mentioned that it could not find the function itself but did find a prototype. I doubt It can be that difficult for the linker to determine that.
I understand every IDE has it's own special behavior, that one experiences and learns about over time but this is confusing. At least i know now that the more strange the error message presented by Visual studio is, the more simple the problem must be.
 

Crusty

Lifer
Sep 30, 2001
12,684
2
81
The compiler thinks everything is just fine because you declared the function.

The linker complains with the error 'unresolved external symbol' when it can't find the definition for the function you declared.

There's a big difference between compiling and linking, and that's what Cogman was getting at. Both tools did their job to their best ability.
 

iCyborg

Golden Member
Aug 8, 2008
1,355
63
91
Well, i can accept that. But it would have been nice if the linker or the compiler just would have mentioned that it could not find the function itself but did find a prototype. I doubt It can be that difficult for the linker to determine that.
I understand every IDE has it's own special behavior, that one experiences and learns about over time but this is confusing. At least i know now that the more strange the error message presented by Visual studio is, the more simple the problem must be.
Well, it did tell you exactly what is wrong if you know how compilation and linking is done. It is not supposed to guess whether you really didn't define the function or didn't link the proper library/object code or something else. And it's not just VS "strangeness", GNU GCC will not give any errors since compiler can't know this during compilation, and the GNU linker will say "undefined reference to 'funcName'" instead of "unresolved external symbol funcName". It's pretty much the same to me.


Compilers can sometimes give abysmal errors though. I still remember one of my first attempts at OOP coding in C++. The code was something like:

Code:
class A 
{
private:
	// some private vars
public:
	A(); // constructor
	int getX();
	// a couple methods
}

A::A()
{
// constructor def
}

...


It was all in one source file, I just wanted to define all methods outside of class declaration.
The error was that I didn't put semicolon after class declaration. The error that compiler gave me was that "a constructor cannot have a return type". I was like in my teens coming from Basic and Pascal with little experience in C/C++ and completely brainf**ked, wtf return type, there is none. I was reading some example from a book, and looking here, and it made no sense to me, I was going crazy for an hour at least. It seems that the compiler (some Borland variety) somehow interpreted the complete class declaration above as the return type of the constructor (declared in that same class decl!).
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
The compiler only knows about the symbols in one translation unit, i.e. a source file and all included headers. If it sees a symbol that has external linkage, and doesn't find a definition for it, it assumes the linker will.
 
May 11, 2008
22,604
1,473
126
It seems we get mixed up.I will try to explain what my issue is here and then you can correct me or not.I do have understanding of a preprocessor, compiler, assembler and a linker but here is the issue :

I have done a "clean solution" and "clean projectname". That should in my opinion mean that there is no more object code laying around.

I use this specific function in my source code. Before the linker can do anything, the compiler must first translate all C code to assembler and the assembler will turn all code into machine instructions. However, some symbols are still unknown because these symbols are dependent on where in the memory layout the symbol is placed. A symbol can for example be a function, a variable, a memory address.

I can understand that the linker cannot find the function because the symbol( i assume found as prototype or just a reference in another source file)exists but the actual function(the source code explaining the function) does not. What i can not understand, is that i use the function in my program, my source code. This means that the c-code(the source code) must be compiled first before it can be linked in. Yet this did not seem to happen. It is until the linker needs the symbol(the missing function) that an error is generated. Now how can this be ? One possibility is that there is still object code existing while i have cleaned my solution/project. Another possibility can be that the compiler compiles unresolved symbols (read functions) only after the linker requests this. And that is what is confusing me.

I do not want to turn this into a flame war.
You do not have to defend visual studio. I still think it is a great program. I just want to understand how this can happen and i would not mind if the error messages would become a bit more clear. But as i have mentioned before, every IDE has it's strange behavior where the programmer has to get used to i guess.

I tested the same issue on an old CVI compiler. CVI does generate an error.
The same issue, the prototype exists but the function does not and is located on another file.

Undefined symbol '_String_Searcher' referenced in "Test_Commands.c" and "Search_Tester.c".

Here is the GNU result for a similar effect :

arm-elf-gcc ./src/isr_asm.o ./src/startup.o ./src/commandcontrol.o ./src/fastexec.o ./src/inithardware.o ./src/isr.o ./src/isr_ctrl.o ./src/low_level_init.o ./src/main.o ./src/os_functions.o ./src/sam7s_hardware.o ./src/semi_stdio.o -mcpu=arm7tdmi -nostartfiles -T./prj/warm_ld.ld -Wl,-Map=./output/bootloader2.map,--cref,--no-warn-mismatch -o output/bootloader2.elf
./src/main.o: In function `main':
e: \arm\project\bootloader2/src/main.c:150: undefined reference to `En_Uart0_Rx_Interrupt'
e: \arm\project\bootloader2/src/main.c:264: undefined reference to `En_Uart0_Rx_Interrupt'
e: \arm\project\bootloader2/src/main.c:248: undefined reference to `En_Uart0_Rx_Interrupt'

collect2: ld returned 1 exit status
make: *** [output/bootloader2.elf] Error 1
I had to add spaces to avoid smileys.

It seems here the linker generates the error as well. But is much clearer as well.
 
Last edited:
May 11, 2008
22,604
1,473
126
The compiler only knows about the symbols in one translation unit, i.e. a source file and all included headers. If it sees a symbol that has external linkage, and doesn't find a definition for it, it assumes the linker will.


That explains it. Thank you.
It seems there is back and forth communication between linker and compiler.
I always assumed it is a straight forward process by use of intermediate files.
Now that i think of it, it makes sense too. I guess i was working to much hours yesterday. :thumbsup:
 

iCyborg

Golden Member
Aug 8, 2008
1,355
63
91
VS: unresolved external symbol X
GNU: undefined reference to X
CVI: undefined symbol X

I don't understand why is the error from GNU "much clearer" than VS. Exact same meaning, just slightly different wording :confused:

And it's not a back-and-forth process, compiler creates object files with 'hooks' for unresolved symbols, linker fills in the addresses afterwards. If some 'hook' is left dangling, linker gives the above error.
 
May 11, 2008
22,604
1,473
126
VS: unresolved external symbol X
GNU: undefined reference to X
CVI: undefined symbol X

I don't understand why is the error from GNU "much clearer" than VS. Exact same meaning, just slightly different wording :confused:

And it's not a back-and-forth process, compiler creates object files with 'hooks' for unresolved symbols, linker fills in the addresses afterwards. If some 'hook' is left dangling, linker gives the above error.

How can the compiler compile source code into an object if the source code is not there ? I mean the missing function contains code. This code must be added as well. When the executable format is formed, the instructions are all packed together as a stream of bytes. To be able to do that, the linker must not only be aware of addresses to relative jump to, it must also calculate these addresses depending on the used space. The distance in memory positions between a calling function and a callee must be taken into account as well. Thus if the compiler never compiled the code how does the linker know ? I assume it does not and that is why the error is generated. The generation of errors is easy then. The compiler just leaves it up to the linker to generate errors if te compiler cannot find the function. It is not just hooks for address calculation to do relative jumps or calls. I like the map files of GNU GCC and the objdump program. It explains a lot and i have found it to be very handy to find errors. Thus it is a straight forward approach all along...

The reason why the GNU and CVI was more clear was because it left out not relevant information. When i am with my head in algorithms i do not care about that the calling conventions is this or that. That is something i use the c language for, that i do not have to think about it.

I feel it is the same as some people who move away from assembler to a higher language as C to
make the code more readable and then make a sport of it to write as cryptic c code as possible. Forgetting the fact that others have to work with that same code as well and bragging how good they are. For some like me, the programming language is just a tool to get where i want to be. It is not the objective self.
 
Last edited:

iCyborg

Golden Member
Aug 8, 2008
1,355
63
91
This is a high-level description of what happens (*I'm not an expert, so some details may be wrong, but hopefully there's nothing conceptually wrong):

Let's say B.cpp has a function call a() from A.cpp

Compiled code for a.cpp would have something like:

void a() {
50000000h // asm code for function a()
50000001h ...
...
5000003Fh ret // return
}


Compiled code for B would have something like:

void b() {
70000000h // asm code for function B
...
70000045h call a // call function a()
...
7000006Ah ret
}


The space for a in 'call a' will be reserved, but the compiler doesn't know where this function will be. When the linker starts linking both code, it sees that a=50000000h and will fill in the correct address of the call instruction. It only needs to insert the address of the symbol, not the complete generated code for it.
How can the compiler compile source code into an object if the source code is not there ? I mean the missing function contains code. This code must be added as well.
No, the code is not necessarily added (it is for inline methods). You only need to know where to jump to, just the address. Think about dynamic linking. There's no machine code to add for some function until runtime!

Thus if the compiler never compiled the code how does the linker know ?
Linking comes after all the specified translation units are compiled, so the linker is the one who does the final layout of the executable and knows where all the addresses are. Once a compiler is done with some translation unit, it will not be touching it again. There's no back-and-forth here, compiler first, then linker.

The reason why the GNU and CVI was more clear was because it left out not relevant information. When i am with my head in algorithms i do not care about that the calling conventions is this or that. That is something i use the c language for, that i do not have to think about it.

I feel it is the same as some people who move away from assembler to a higher language as C to
make the code more readable and then make a sport of it to write as cryptic c code as possible. Forgetting the fact that others have to work with that same code as well and bragging how good they are. For some like me, the programming language is just a tool to get where i want to be. It is not the objective self.
I prefer that the compiler/linker doesn't guess which information I may or may not need, and instead give everything that could be relevant. And one word hardly makes it much less clearer... If you don't understand an error, google it :p
 
May 11, 2008
22,604
1,473
126
This is a high-level description of what happens (*I'm not an expert, so some details may be wrong, but hopefully there's nothing conceptually wrong):

Let's say B.cpp has a function call a() from A.cpp

Compiled code for a.cpp would have something like:

void a() {
50000000h // asm code for function a()
50000001h ...
...
5000003Fh ret // return
}


Compiled code for B would have something like:

void b() {
70000000h // asm code for function B
...
70000045h call a // call function a()
...
7000006Ah ret
}


The space for a in 'call a' will be reserved, but the compiler doesn't know where this function will be. When the linker starts linking both code, it sees that a=50000000h and will fill in the correct address of the call instruction. It only needs to insert the address of the symbol, not the complete generated code for it.
No, the code is not necessarily added (it is for inline methods). You only need to know where to jump to, just the address. Think about dynamic linking. There's no machine code to add for some function until runtime!

I primarily use C for an embedded system i am making myself. I never use dynamic linking. But i understand what you mean.


Linking comes after all the specified translation units are compiled, so the linker is the one who does the final layout of the executable and knows where all the addresses are. Once a compiler is done with some translation unit, it will not be touching it again. There's no back-and-forth here, compiler first, then linker.

I prefer that the compiler/linker doesn't guess which information I may or may not need, and instead give everything that could be relevant. And one word hardly makes it much less clearer... If you don't understand an error, google it :p

I did google it. I did search for it first. But the microsoft page presented me with more and more options what could be wrong. I decided that there was no relevant information and backtracked what i did wrong. After that i understood what was wrong. When it comes to presenting extended error messages, i prefer a simple message what is wrong with the option of a fully detailed explanation if i desire it. It is a matter of opinion how people like their tools.
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
It's confusing until you get it, and then once you do you'll always understand what the compiler and linker are doing, and why certain errors occur. The key points, imo...

- The compiler's job is to process a translation unit into a binary object. A translation unit is a source file and all included headers, comprising a single virtual body of text that is processed top-down. The compiler doesn't know about anything at all outside that translation unit, so every symbol it encounters must be in a declaration or definition, or must have been previously declared or defined.

-A declaration exists when the name and type of a variable are introduced in a translation unit. These are both declarations...

extern int a;
void foo();

Neither of these is a definition. A definition specifies the actual storage that contains a variable in the data segment, or a function in a code segment. Neither of these defines storage. They simply introduce a name, and would usually occur in a header file. Yet that is enough for the compiler to manage references to them. When it sees that a program references variable a, or calls foo(), it hasn't seen a definition yet. It doesn't know the actual address of a or foo(), so it just puts in a placeholder that says "referencing the value of a here", or "calling foo here."

These are definitions...

int a;
void foo()
{
// blah
}

Both of these specify the full contents of a piece of named storage. Data in the first case, code in the second. There are both also declarations, since both also introduce a named object of a specific type. Every definition in C++ is also a declaration, but not all declarations are definitions.

- The linker's job is to take all the binary objects the compiler produced and pack them into a single binary executable or library, and in the process fix up the references between modules that the compiler couldn't deal with. What needs to be fixed specifically are those calls and references where the compiler had a declaration, but no definition (because the variable or function is defined in another translation unit).

Hopefully it will be clear why the second stage, the link, might fail with an "undefined symbol" error. Suppose...

extern int a;
void foo()
{
a = 1;
}

Suppose that a is not defined in any other translation unit. The compiler compiles this code into a binary object without problems because it knows all it needs to know about a: it's an int named 'a'. In the object it places a little sign saying "referencing an int named a here." The linker then goes to work and sees that sign and looks for the actual definition of 'a' so it can fix up the reference. If it isn't found, you get the undefined symbol error.
 

Merad

Platinum Member
May 31, 2010
2,586
19
81
I can understand that the linker cannot find the function because the symbol( i assume found as prototype or just a reference in another source file)exists but the actual function(the source code explaining the function) does not. What i can not understand, is that i use the function in my program, my source code. This means that the c-code(the source code) must be compiled first before it can be linked in. Yet this did not seem to happen. It is until the linker needs the symbol(the missing function) that an error is generated. Now how can this be ? One possibility is that there is still object code existing while i have cleaned my solution/project. Another possibility can be that the compiler compiles unresolved symbols (read functions) only after the linker requests this. And that is what is confusing me.

When the compiler needs to call a function, all it needs to know is what parameters the function requires and what value it will return. It doesn't care where the function is actually located. When the linker actually creates the executable, it will supply the address for the function.

Say you have a simple function void foo(int i). To call the function such as foo(1), the compiler will generate code basically equivalent to the asm

push 1
call function_foo
add esp, 4 ; assuming 4 byte int

That's all the compiler needs to do. Push the function's argument onto the stack, call the function, and cleanup the stack afterwards. When the linker does its job, it will generate a symbol function_foo, and give it the actual address where the function exists in the executable image.

If the linker can't find the function anywhere, then you get those wonderful undefined symbol errors.
 
May 11, 2008
22,604
1,473
126
Aaaaaaah..... (experiencing and enjoying relieve) :wub:
Thank you all for the refreshing and the confirmation.

The healing power of a good social setting. Social, the word that so much people despise while experiencing it every day and taking it for granted.
No technology can continue to exist without social behavior performing correcting or confirming actions.
 
May 11, 2008
22,604
1,473
126
I just got the same error again.

makefilescript_generator.obj : error LNK2019: unresolved external symbol "void __cdecl AddProjectName(char *,int)" (?AddProjectName@@YAXPADH@Z) referenced in function "int __cdecl Create_Makefile_File(struct struct_configdata *,void *)" (?Create_Makefile_File@@YAHPAUstruct_configdata@@PAX@Z)
E: \My docs\Visual Studio 2008\Projects\unicodetest\William Release\unicodetest.exe : fatal error LNK1120: 1 unresolved externals

But this time the function did exist in source and header file. The difference was a missing variable in the AddProjectName(missing variable, variable, variable ) function definition in the source file.

It works fine now by the way.
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
I just got the same error again.



But this time the function did exist in source and header file. The difference was a missing variable in the AddProjectName(missing variable, variable, variable ) function definition in the source file.

It works fine now by the way.

Yep, in C++ the function parameters are part of the type signature of the function. Wasn't always that way in C if I recall correctly.
 

Cogman

Lifer
Sep 19, 2000
10,286
147
106
Yep, in C++ the function parameters are part of the type signature of the function. Wasn't always that way in C if I recall correctly.

Ahh the C++ name mangling scheme. What a wonderful thing :D. makes it REALLY fun when you want to use C++ with other programming languages.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
But you gotta love overloading. I think "extern C" turns mangling off, right?

C++ mangling, yes. Symbols declared extern C must have C-style linkage, which is the standard for inter-language operation. Dynamic libraries, for instance, export their top-layer symbols with C symbols, so dlopen() can go searching for symbols at runtime.