Some more complex builds may not support this. For example, if you include -v in the compiler options, you can see that the mainwin gcc wrapper mwdip discards linker script command files in the verbose output list of libraries to link in. A simple work around is to replace the linker script input command file with a copy of the file instead (or a symlink), e.g.
cp libtbb.so.2 libtbb.so
Or you could replace the -l argument with the full path of the .so, e.g. instead of -ltbb do /home/foo/tbb-4.3/linux/lib/intel64/gcc4.4/libtbb.so.2
$ gcc -o eg1 -L. -lmy_lib eg1.o
eg1.o: In function `main':
eg1.c:(.text+0x5): undefined reference to `hw'
collect2: error: ld returned 1 exit status
The same result if you compile and link in one step, like:
$ gcc -o eg1 -I. -L. -lmy_lib eg1.c
/tmp/ccQk1tvs.o: In function `main':
eg1.c:(.text+0x5): undefined reference to `hw'
collect2: error: ld returned 1 exit status
A minimal example involving a shared system library, the compression library libz
eg2.c
# include <zlib.h>
# include <stdio.h>
int main()
{
printf("%s\n",zlibVersion());
return 0;
}
Compile your program:
$ gcc -c -o eg2.o eg2.c
Try to link your program with libz and fail:
$ gcc -o eg2 -lz eg2.o
eg2.o: In function `main':
eg2.c:(.text+0x5): undefined reference to `zlibVersion'
collect2: error: ld returned 1 exit status
Same if you compile and link in one go:
$ gcc -o eg2 -I. -lz eg2.c
/tmp/ccxCiGn7.o: In function `main':
eg2.c:(.text+0x5): undefined reference to `zlibVersion'
collect2: error: ld returned 1 exit status
And a variation on example 2 involving pkg-config:
$ gcc -o eg2 $(pkg-config --libs zlib) eg2.o
eg2.o: In function `main':
eg2.c:(.text+0x5): undefined reference to `zlibVersion'
What are you doing wrong?
In the sequence of object files and libraries you want to link to make your program, you are placing the libraries before the object files that refer to them. You need to place the libraries after the object files that refer to them.
Link example 1 correctly:
$ gcc -o eg1 eg1.o -L. -lmy_lib
Success:
$ ./eg1
Hello World
Link example 2 correctly:
$ gcc -o eg2 eg2.o -lz
Success:
$ ./eg2
1.2.8
Link the example 2 pkg-config variation correctly:
By default, a linkage command generated by GCC, on your distro, consumes the files in the linkage from left to right in commandline sequence. When it finds that a file refers to something and does not contain a definition for it, to will search for a definition in files further to the right. If it eventually finds a definition, the reference is resolved. If any references remain unresolved at the end, the linkage fails: the linker does not search backwards.
First,example 1, with static library my_lib.a
A static library is an indexed archive of object files. When the linker finds -lmy_lib in the linkage sequence and figures out that this refers to the static library ./libmy_lib.a, it wants to know whether your program needs any of the object files in libmy_lib.a.
There is only object file in libmy_lib.a, namely my_lib.o, and there's only one thing defined in my_lib.o, namely the function hw.
The linker will decide that your program needs my_lib.o if and only if it already knows that your program refers to hw, in one or more of the object files it has already added to the program, and that none of the object files it has already added contains a definition for hw.
If that is true, then the linker will extract a copy of my_lib.o from the library and add it to your program. Then, your program contains a definition for hw, so its references to hw are resolved.
When you try to link the program like:
$ gcc -o eg1 -L. -lmy_lib eg1.o
the linker has not addedeg1.oto the program when it sees -lmy_lib. Because at that point, it has not seen eg1.o. Your program does not yet make any references to hw: it does not yet make any references at all, because all the references it makes are in eg1.o.
So the linker does not add my_lib.o to the program and has no further use for libmy_lib.a.
Next, it finds eg1.o, and adds it to be program. An object file in the linkage sequence is always added to the program. Now, the program makes a reference to hw, and does not contain a definition of hw; but there is nothing left in the linkage sequence that could provide the missing definition. The reference to hw ends up unresolved, and the linkage fails.
Second,example 2, with shared library libz
A shared library isn't an archive of object files or anything like it. It's much more like a program that doesn't have a main function and instead exposes multiple other symbols that it defines, so that other programs can use them at runtime.
Many Linux distros today configure their GCC toolchain so that its language drivers (gcc,g++,gfortran etc) instruct the system linker (ld) to link shared libraries on an as-needed basis. You have got one of those distros.
This means that when the linker finds -lz in the linkage sequence, and figures out that this refers to the shared library (say) /usr/lib/x86_64-linux-gnu/libz.so, it wants to know whether any references that it has added to your program that aren't yet defined have definitions that are exported by libz
If that is true, then the linker will not copy any chunks out of libz and add them to your program; instead, it will just doctor the code of your program so that:-
At runtime, the system program loader will load a copy of libz into the same process as your program whenever it loads a copy of your program, to run it.
At runtime, whenever your program refers to something that is defined in libz, that reference uses the definition exported by the copy of libz in the same process.
Your program wants to refer to just one thing that has a definition exported by libz, namely the function zlibVersion, which is referred to just once, in eg2.c. If the linker adds that reference to your program, and then finds the definition exported by libz, the reference is resolved
But when you try to link the program like:
gcc -o eg2 -lz eg2.o
the order of events is wrong in just the same way as with example 1. At the point when the linker finds -lz, there are no references to anything in the program: they are all in eg2.o, which has not yet been seen. So the linker decides it has no use for libz. When it reaches eg2.o, adds it to the program, and then has undefined reference to zlibVersion, the linkage sequence is finished; that reference is unresolved, and the linkage fails.
Lastly, the pkg-config variation of example 2 has a now obvious explanation. After shell-expansion:
gcc -o eg2 $(pkg-config --libs zlib) eg2.o
becomes:
gcc -o eg2 -lz eg2.o
which is just example 2 again.
I can reproduce the problem in example 1, but not in example 2
The linkage:
gcc -o eg2 -lz eg2.o
works just fine for you!
(Or: That linkage worked fine for you on, say, Fedora 23, but fails on Ubuntu 16.04)
That's because the distro on which the linkage works is one of the ones that does not configure its GCC toolchain to link shared libraries as-needed.
Back in the day, it was normal for unix-like systems to link static and shared libraries by different rules. Static libraries in a linkage sequence were linked on the as-needed basis explained in example 1, but shared libraries were linked unconditionally.
This behaviour is economical at linktime because the linker doesn't have to ponder whether a shared library is needed by the program: if it's a shared library, link it. And most libraries in most linkages are shared libraries. But there are disadvantages too:-
It is uneconomical at runtime, because it can cause shared libraries to be loaded along with a program even if doesn't need them.
The different linkage rules for static and shared libraries can be confusing to inexpert programmers, who may not know whether -lfoo in their linkage is going to resolve to /some/where/libfoo.a or to /some/where/libfoo.so, and might not understand the difference between shared and static libraries anyway.
This trade-off has led to the schismatic situation today. Some distros have changed their GCC linkage rules for shared libraries so that the as-needed principle applies for all libraries. Some distros have stuck with the old way.
Why do I still get this problem even if I compile-and-link at the same time?
If I just do:
$ gcc -o eg1 -I. -L. -lmy_lib eg1.c
surely gcc has to compile eg1.c first, and then link the resulting object file with libmy_lib.a. So how can it not know that object file is needed when it's doing the linking?
Because compiling and linking with a single command does not change the order of the linkage sequence.
When you run the command above, gcc figures out that you want compilation + linkage. So behind the scenes, it generates a compilation command, and runs it, then generates a linkage command, and runs it, as if you had run the two commands:
So the linkage fails just as it does if you do run those two commands. The only difference you notice in the failure is that gcc has generated a temporary object file in the compile + link case, because you're not telling it to use eg1.o. We see:
Putting interdependent libraries in the wrong order is just one way in which you can get files that need definitions of things coming later in the linkage than the files that provide the definitions. Putting libraries before the object files that refer to them is another way of making the same mistake.
Since people seem to be directed to this question when it comes to linker errors I am going to add this here.
One possible reason for linker errors with GCC 5.2.0 is that a new libstdc++ library ABI is now chosen by default. If you get linker errors about undefined references to symbols that involve types in the std::__cxx11 namespace or the tag [abi:cxx11] then it probably indicates that you are trying to link together object files that were compiled with different values for the _GLIBCXX_USE_CXX11_ABI macro. This commonly happens when linking to a third-party library that was compiled with an older version of GCC. If the third-party library cannot be rebuilt with the new ABI then you will need to recompile your code with the old ABI.
So if you suddenly get linker errors when switching to a GCC after 5.1.0 this would be a thing to check out.
I had the same issue. Say i have projects MyProject and TestProject. I had effectively linked the lib file for MyProject to the TestProject. However, this lib file was produced as the DLL for the MyProject was built. Also, I did not contain source code for all methods in the MyProject, but only access to the DLL's entry points.
To solve the issue, i built the MyProject as a LIB, and linked TestProject to this .lib file (i copy paste the generated .lib file into the TestProject folder). I can then build again MyProject as a DLL. It is compiling since the lib to which TestProject is linked does contain code for all methods in classes in MyProject.
I recently had this problem, and it turned out it was a bug in Visual Studio Express 2013. I had to remove a source file from the project and re-add it to overcome the bug.
Steps to try if you believe it could be a bug in compiler/IDE:
Clean the project (some IDEs have an option to do this, you can also manually do it by deleting the object files)
Try start a new project, copying all source code from the original one.
I was recently able to get rid of an unresolved external error in Visual Studio 2012 just by recompiling the offending file. When I re-built, the error went away.
This usually happens when two (or more) libraries have a cyclic dependency. Library A attempts to use symbols in B.lib and library B attempts to use symbols from A.lib. Neither exist to start off with. When you attempt to compile A, the link step will fail because it can't find B.lib. A.lib will be generated, but no dll. You then compile B, which will succeed and generate B.lib. Re-compiling A will now work because B.lib is now found.
Unspecialized templates must have their definitions visible to all translation units that use them. That means you can't separate the definition of a template to an implementation file. If you must separate the implementation, the usual workaround is to have an impl file which you include at the end of the header that declares the template. A common situation is:
To fix this, you must move the definition of X::foo to the header file or some place visible to the translation unit that uses it.
Specialized templates can be implemented in an implementation file and the implementation doesn't have to be visible, but the specialization must be previously declared.
For further explanation and another possible solution (explicit instantiation) see this question and answer.
This is one of most confusing error messages that every VC++ programmers have seen time and time again. Let’s make things clarity first.
**A. What is symbol?**In short, a symbol is a name. It can be a variable name, a function name, a class name, a typedef name, or anything except those names and signs that belong to C++ language. It is user defined or introduced by a dependency library (another user-defined).
**B. What is external?**In VC++, every source file (.cpp,.c,etc.) is considered as a translation unit, the compiler compiles one unit at a time, and generate one object file(.obj) for the current translation unit. (Note that every header file that this source file included will be preprocessed and will be considered as part of this translation unit)Everything within a translation unit is considered as internal, everything else is considered as external. In C++, you may reference an external symbol by using keywords like extern, __declspec (dllimport) and so on.
**C. What is “resolve”?**Resolve is a linking-time term. In linking-time, linker attempts to find the external definition for every symbol in object files that cannot find its definition internally. The scope of this searching process including:
All object files that generated in compiling time
All libraries (.lib) that are either explicitly or implicitly specified as additional dependencies of this building application.
This searching process is called resolve.
**D. Finally, why Unresolved External Symbol?**If the linker cannot find the external definition for a symbol that has no definition internally, it reports an Unresolved External Symbol error.
E. Possible causes of LNK2019: Unresolved External Symbol error. We already know that this error is due to the linker failed to find the definition of external symbols, the possible causes can be sorted as:
Definition exists
For example, if we have a function called foo defined in a.cpp:
int foo()
{
return 0;
}
In b.cpp we want to call function foo, so we add
void foo();
to declare function foo(), and call it in another function body, say bar():
void bar()
{
foo();
}
Now when you build this code you will get a LNK2019 error complaining that foo is an unresolved symbol. In this case, we know that foo() has its definition in a.cpp, but different from the one we are calling(different return value). This is the case that definition exists.
Definition does not exist
If we want to call some functions in a library, but the import library is not added into the additional dependency list (set from: Project | Properties | Configuration Properties | Linker | Input | Additional Dependency) of your project setting. Now the linker will report a LNK2019 since the definition does not exist in current searching scope.
The macro THIS_MODULE would only be defined in the module that exports the function. That way, the declaration:
DLLIMPEXP void foo();
expands to
__declspec(dllexport) void foo();
and tells the compiler to export the function, as the current module contains its definition. When including the declaration in a different module, it would expand to
__declspec(dllimport) void foo();
and tells the compiler that the definition is in one of the libraries you linked against (also see1)).
undefined reference to WinMain@16 or similar 'unusual'main() entry point reference(especially for visual-studio).
You may have missed to choose the right project type with your actual IDE. The IDE may want to bind e.g. Windows Application projects to such entry point function (as specified in the missing reference above), instead of the commonly used int main(int argc, char**argv); signature.
If your IDE supports Plain Console Projects you might want to choose this project type, instead of a windows application project.
Here are case1 and case2 handled in more detail from a real world problem.
我通过在该文件中找到packagename\build\native\packagename.targets并复制所有v110节来编辑包(在解决方案目录内的packages文件夹中)。我将**条件字段中的v110更改为v120**非常小心地将文件名路径全部保留为v110。这只是允许Visual Studio 2013链接到2012年的库,在这种情况下,它起作用了。
29条答案
按热度按时间rxztt3cl1#
针对共享库进行链接时,请确保使用的符号没有隐藏。
GCC的默认行为是所有符号都是可见的。但是,当使用选项
-fvisibility=hidden
构建转换单元时,只有标有__attribute__ ((visibility ("default")))
的函数/符号在生成的共享对象中是外部的。您可以通过调用以下命令来检查您正在寻找的符号是否为外部符号:
隐藏/本地符号由
nm
显示,符号类型为小写,例如t
而不是代码段的`t:您还可以使用带有选项
-C
的nm
来取消名称的混乱(如果使用的是C++)。与Windows-dll类似,可以使用定义标记公共函数,例如
DLL_PUBLIC
定义为:大致对应于Windows的/MSVC版本:
更多information about visibility可以在GCC维基上找到。
当用
-fvisibility=hidden
编译翻译单元时,所得到的符号仍然具有外部链接(由nm
以大写符号类型表示),并且如果目标文件成为静态库的一部分,则可以用于外部链接而没有问题。仅当目标文件链接到共享库时,该链接才变为本地链接。要查找对象文件中隐藏的符号,请执行以下操作:
tgabmvqs2#
A wrapper around GNU ld that doesn't support linker scripts
Some .so files are actually GNU ld linker scripts, e.g. libtbb.so file is an ASCII text file with this contents:
Some more complex builds may not support this. For example, if you include -v in the compiler options, you can see that the mainwin gcc wrapper mwdip discards linker script command files in the verbose output list of libraries to link in. A simple work around is to replace the linker script input command file with a copy of the file instead (or a symlink), e.g.
Or you could replace the -l argument with the full path of the .so, e.g. instead of
-ltbb
do/home/foo/tbb-4.3/linux/lib/intel64/gcc4.4/libtbb.so.2
mccptt673#
Your linkage consumes libraries before the object files that refer to them
libfoo
depends onlibbar
, then your linkage correctly putslibfoo
beforelibbar
.undefined reference to
something errors.#include
d and are in fact defined in the libraries that you are linking.Examples are in C. They could equally well be C++
A minimal example involving a static library you built yourself
my_lib.c
my_lib.h
eg1.c
You build your static library:
You compile your program:
You try to link it with
libmy_lib.a
and fail:The same result if you compile and link in one step, like:
A minimal example involving a shared system library, the compression library
libz
eg2.c
Compile your program:
Try to link your program with
libz
and fail:Same if you compile and link in one go:
And a variation on example 2 involving
pkg-config
:What are you doing wrong?
In the sequence of object files and libraries you want to link to make your program, you are placing the libraries before the object files that refer to them. You need to place the libraries after the object files that refer to them.
Link example 1 correctly:
Success:
Link example 2 correctly:
Success:
Link the example 2
pkg-config
variation correctly:The explanation
By default, a linkage command generated by GCC, on your distro, consumes the files in the linkage from left to right in commandline sequence. When it finds that a file refers to something and does not contain a definition for it, to will search for a definition in files further to the right. If it eventually finds a definition, the reference is resolved. If any references remain unresolved at the end, the linkage fails: the linker does not search backwards.
First,example 1, with static library
my_lib.a
A static library is an indexed archive of object files. When the linker finds
-lmy_lib
in the linkage sequence and figures out that this refers to the static library./libmy_lib.a
, it wants to know whether your program needs any of the object files inlibmy_lib.a
.There is only object file in
libmy_lib.a
, namelymy_lib.o
, and there's only one thing defined inmy_lib.o
, namely the functionhw
.The linker will decide that your program needs
my_lib.o
if and only if it already knows that your program refers tohw
, in one or more of the object files it has already added to the program, and that none of the object files it has already added contains a definition forhw
.If that is true, then the linker will extract a copy of
my_lib.o
from the library and add it to your program. Then, your program contains a definition forhw
, so its references tohw
are resolved.When you try to link the program like:
the linker has not added
eg1.o
to the program when it sees-lmy_lib
. Because at that point, it has not seeneg1.o
. Your program does not yet make any references tohw
: it does not yet make any references at all, because all the references it makes are ineg1.o
.So the linker does not add
my_lib.o
to the program and has no further use forlibmy_lib.a
.Next, it finds
eg1.o
, and adds it to be program. An object file in the linkage sequence is always added to the program. Now, the program makes a reference tohw
, and does not contain a definition ofhw
; but there is nothing left in the linkage sequence that could provide the missing definition. The reference tohw
ends up unresolved, and the linkage fails.Second,example 2, with shared library
libz
A shared library isn't an archive of object files or anything like it. It's much more like a program that doesn't have a
main
function and instead exposes multiple other symbols that it defines, so that other programs can use them at runtime.Many Linux distros today configure their GCC toolchain so that its language drivers (
gcc
,g++
,gfortran
etc) instruct the system linker (ld
) to link shared libraries on an as-needed basis. You have got one of those distros.This means that when the linker finds
-lz
in the linkage sequence, and figures out that this refers to the shared library (say)/usr/lib/x86_64-linux-gnu/libz.so
, it wants to know whether any references that it has added to your program that aren't yet defined have definitions that are exported bylibz
If that is true, then the linker will not copy any chunks out of
libz
and add them to your program; instead, it will just doctor the code of your program so that:-libz
into the same process as your program whenever it loads a copy of your program, to run it.libz
, that reference uses the definition exported by the copy oflibz
in the same process.Your program wants to refer to just one thing that has a definition exported by
libz
, namely the functionzlibVersion
, which is referred to just once, ineg2.c
. If the linker adds that reference to your program, and then finds the definition exported bylibz
, the reference is resolvedBut when you try to link the program like:
the order of events is wrong in just the same way as with example 1. At the point when the linker finds
-lz
, there are no references to anything in the program: they are all ineg2.o
, which has not yet been seen. So the linker decides it has no use forlibz
. When it reacheseg2.o
, adds it to the program, and then has undefined reference tozlibVersion
, the linkage sequence is finished; that reference is unresolved, and the linkage fails.Lastly, the
pkg-config
variation of example 2 has a now obvious explanation. After shell-expansion:becomes:
which is just example 2 again.
I can reproduce the problem in example 1, but not in example 2
The linkage:
works just fine for you!
(Or: That linkage worked fine for you on, say, Fedora 23, but fails on Ubuntu 16.04)
That's because the distro on which the linkage works is one of the ones that does not configure its GCC toolchain to link shared libraries as-needed.
Back in the day, it was normal for unix-like systems to link static and shared libraries by different rules. Static libraries in a linkage sequence were linked on the as-needed basis explained in example 1, but shared libraries were linked unconditionally.
This behaviour is economical at linktime because the linker doesn't have to ponder whether a shared library is needed by the program: if it's a shared library, link it. And most libraries in most linkages are shared libraries. But there are disadvantages too:-
-lfoo
in their linkage is going to resolve to/some/where/libfoo.a
or to/some/where/libfoo.so
, and might not understand the difference between shared and static libraries anyway.This trade-off has led to the schismatic situation today. Some distros have changed their GCC linkage rules for shared libraries so that the as-needed principle applies for all libraries. Some distros have stuck with the old way.
Why do I still get this problem even if I compile-and-link at the same time?
If I just do:
surely gcc has to compile
eg1.c
first, and then link the resulting object file withlibmy_lib.a
. So how can it not know that object file is needed when it's doing the linking?Because compiling and linking with a single command does not change the order of the linkage sequence.
When you run the command above,
gcc
figures out that you want compilation + linkage. So behind the scenes, it generates a compilation command, and runs it, then generates a linkage command, and runs it, as if you had run the two commands:So the linkage fails just as it does if you do run those two commands. The only difference you notice in the failure is that gcc has generated a temporary object file in the compile + link case, because you're not telling it to use
eg1.o
. We see:instead of:
See also
The order in which interdependent linked libraries are specified is wrong
Putting interdependent libraries in the wrong order is just one way in which you can get files that need definitions of things coming later in the linkage than the files that provide the definitions. Putting libraries before the object files that refer to them is another way of making the same mistake.
vuktfyat4#
Since people seem to be directed to this question when it comes to linker errors I am going to add this here.
One possible reason for linker errors with GCC 5.2.0 is that a new libstdc++ library ABI is now chosen by default.
If you get linker errors about undefined references to symbols that involve types in the std::__cxx11 namespace or the tag [abi:cxx11] then it probably indicates that you are trying to link together object files that were compiled with different values for the _GLIBCXX_USE_CXX11_ABI macro. This commonly happens when linking to a third-party library that was compiled with an older version of GCC. If the third-party library cannot be rebuilt with the new ABI then you will need to recompile your code with the old ABI.
So if you suddenly get linker errors when switching to a GCC after 5.1.0 this would be a thing to check out.
qlzsbp2j5#
Linked .lib file is associated to a .dll
I had the same issue. Say i have projects MyProject and TestProject. I had effectively linked the lib file for MyProject to the TestProject. However, this lib file was produced as the DLL for the MyProject was built. Also, I did not contain source code for all methods in the MyProject, but only access to the DLL's entry points.
To solve the issue, i built the MyProject as a LIB, and linked TestProject to this .lib file (i copy paste the generated .lib file into the TestProject folder). I can then build again MyProject as a DLL. It is compiling since the lib to which TestProject is linked does contain code for all methods in classes in MyProject.
8wigbo566#
A bug in the compiler/IDE
I recently had this problem, and it turned out it was a bug in Visual Studio Express 2013. I had to remove a source file from the project and re-add it to overcome the bug.
Steps to try if you believe it could be a bug in compiler/IDE:
r7xajy2e7#
使用链接器帮助诊断错误
大多数现代链接器都包含一个详细的选项,可以打印出不同程度的内容;
对于GCC和Clang,您通常会将
-v -Wl,--verbose
或-v -Wl,-v
添加到命令行。更多细节可以在这里找到;对于MSVC,将
/VERBOSE
(特别是/VERBOSE:LIB
)添加到链接命令行。/VERBOSE
linker option上的MSDN页面。fslejnso8#
If all else fails, recompile.
I was recently able to get rid of an unresolved external error in Visual Studio 2012 just by recompiling the offending file. When I re-built, the error went away.
This usually happens when two (or more) libraries have a cyclic dependency. Library A attempts to use symbols in B.lib and library B attempts to use symbols from A.lib. Neither exist to start off with. When you attempt to compile A, the link step will fail because it can't find B.lib. A.lib will be generated, but no dll. You then compile B, which will succeed and generate B.lib. Re-compiling A will now work because B.lib is now found.
dw1jzc5e9#
Template implementations not visible.
Unspecialized templates must have their definitions visible to all translation units that use them. That means you can't separate the definition of a template to an implementation file. If you must separate the implementation, the usual workaround is to have an
impl
file which you include at the end of the header that declares the template. A common situation is:To fix this, you must move the definition of
X::foo
to the header file or some place visible to the translation unit that uses it.Specialized templates can be implemented in an implementation file and the implementation doesn't have to be visible, but the specialization must be previously declared.
For further explanation and another possible solution (explicit instantiation) see this question and answer.
sulc1iza10#
This is one of most confusing error messages that every VC++ programmers have seen time and time again. Let’s make things clarity first.
**A. What is symbol?**In short, a symbol is a name. It can be a variable name, a function name, a class name, a typedef name, or anything except those names and signs that belong to C++ language. It is user defined or introduced by a dependency library (another user-defined).
**B. What is external?**In VC++, every source file (.cpp,.c,etc.) is considered as a translation unit, the compiler compiles one unit at a time, and generate one object file(.obj) for the current translation unit. (Note that every header file that this source file included will be preprocessed and will be considered as part of this translation unit)Everything within a translation unit is considered as internal, everything else is considered as external. In C++, you may reference an external symbol by using keywords like
extern
,__declspec (dllimport)
and so on.**C. What is “resolve”?**Resolve is a linking-time term. In linking-time, linker attempts to find the external definition for every symbol in object files that cannot find its definition internally. The scope of this searching process including:
This searching process is called resolve.
**D. Finally, why Unresolved External Symbol?**If the linker cannot find the external definition for a symbol that has no definition internally, it reports an Unresolved External Symbol error.
E. Possible causes of LNK2019: Unresolved External Symbol error. We already know that this error is due to the linker failed to find the definition of external symbols, the possible causes can be sorted as:
For example, if we have a function called foo defined in a.cpp:
In b.cpp we want to call function foo, so we add
to declare function foo(), and call it in another function body, say
bar()
:Now when you build this code you will get a LNK2019 error complaining that foo is an unresolved symbol. In this case, we know that foo() has its definition in a.cpp, but different from the one we are calling(different return value). This is the case that definition exists.
If we want to call some functions in a library, but the import library is not added into the additional dependency list (set from:
Project | Properties | Configuration Properties | Linker | Input | Additional Dependency
) of your project setting. Now the linker will report a LNK2019 since the definition does not exist in current searching scope.iyzzxitl11#
Incorrectly importing/exporting methods/classes across modules/dll (compiler specific).
MSVS requires you to specify which symbols to export and import using
__declspec(dllexport)
and__declspec(dllimport)
.This dual functionality is usually obtained through the use of a macro:
The macro
THIS_MODULE
would only be defined in the module that exports the function. That way, the declaration:expands to
and tells the compiler to export the function, as the current module contains its definition. When including the declaration in a different module, it would expand to
and tells the compiler that the definition is in one of the libraries you linked against (also see1)).
You can similary import/export classes:
pkbketx912#
undefined reference to
WinMain@16
or similar 'unusual'main()
entry point reference(especially for visual-studio).You may have missed to choose the right project type with your actual IDE. The IDE may want to bind e.g. Windows Application projects to such entry point function (as specified in the missing reference above), instead of the commonly used
int main(int argc, char**argv);
signature.If your IDE supports Plain Console Projects you might want to choose this project type, instead of a windows application project.
Here are case1 and case2 handled in more detail from a real world problem.
nzrxty8p13#
另外,如果您使用的是第三方库,请确保您拥有正确的32/64位二进制文件
r1zk6ea114#
微软提供了一个
#pragma
来在链接时引用正确的库;除了包括库目录的库路径外,这还应该是库的全名。
gxwragnw15#
需要为新的工具集版本更新Visual Studio NuGet包
我在尝试将libpng链接到Visual Studio 2013时遇到了这个问题。问题是,程序包文件只有用于Visual Studio2010和2012的库。
正确的解决方案是希望开发人员发布一个更新的包,然后进行升级,但这对我来说很管用,我破解了VS2013的一个额外设置,指向VS2012库文件。
我通过在该文件中找到
packagename\build\native\packagename.targets
并复制所有v110
节来编辑包(在解决方案目录内的packages
文件夹中)。我将**条件字段中的v110
更改为v120
**非常小心地将文件名路径全部保留为v110
。这只是允许Visual Studio 2013链接到2012年的库,在这种情况下,它起作用了。