VC++ Error LNK2001无法解析的外部符号 的几种情况及解决办法

本文总结了VC++编程中常见的LNK2001错误及其解决方案,包括编码错误、编译链接设置不当等原因。

今天写了一个堆栈小程序,然后碰到了“Error LNK2001 无法解析的外部符号”这个问题,一直解决不了,后来上网搜了下,发现这里面的关于这类错误的内容归纳比较齐全,就摘下来作为参考了。


原文: http://wenku.baidu.com/view/8f0e877931b765ce0508141a.html


VC++时经常会遇到链接错误LNK2001,该错误非常讨厌,因为对于编程者来说,最好改的错误莫过于编译错误,而一般说来发生连接错误时,编译都已通过。产生连接错误的原因非常多,尤其LNK2001错误,常常使人不明其所以然。如果不深入地学习和理解VC++,要想改正连接错误LNK2001非常困难。初学者在学习VC++的过程中,遇到的LNK2001错误的错误消息主要为:   unresolved   external   symbol   “symbol”(不确定的外部“符号”)。如果连接程序不能在所有的库和目标文件内找到所引用的函数、变量或标签,将产生此错误消息。一般来说,发生错误的原因有两个:一是所引用 的函数、变量不存在、拼写不正确或者使用错误;其次可能使用了不同版本 的连接库。   


以下是可能产生LNK2001错误的原因:   
一.由于编码错误导致的LNK2001。   
1.不相匹配的程序代码或模块定义(.DEF)文件能导致LNK2001。例如,  如果在C++   源文件内声明了一变量“var1”,却试图在另一文件内以变量 “VAR1”访问该变量,将发生该错误。   
2.如果使用的内联函数是在.CPP文件内定义的,而不是在头文件内定义将导致LNK2001错误。 
3.调用函数时如果所用的参数类型同函数声明时的类型不符将会产生LNK2001。   
4.试图从基类的构造函数或析构函数中调用虚拟函数时将会导致LNK2001。   

5.要注意函数和变量的可公用性,只有全局变量、函数是可公用的。静态函数和静态变量具有相同的使用范围限制。当试图从文件外部访问任何没有在该文件内声明的静态变量时将导致编译错误或LNK2001。函数内声明的变量(局部变量)只能在该函数的范围内使用。C++的全局常量只有静态连接性能。这不同于C,如果试图在C++的多个文件内使用全局变量也会产生LNK2001错误。一种解决的方法是需要时在头文件中加入该常量的初始化代码,并在.CPP文件中包含该头文件;另一种 方法是使用时给该变量赋以常数。

   

二.由于编译和链接的设置而造成的LNK2001   
1.如果编译时使用的是/NOD(/NODEFAULTLIB)选项,程序所需要的运行库和MFC库在连接时由编译器写入目标文件模块,   但除非在文件中明确包含这些库名,否则这些库不会被链接进工程文件。在这种情况下使用/NOD将导 致错误LNK2001。 
2.如果没有为wWinMainCRTStartup设定程序入口,在使用Unicode和MFC时将得到“unresolved   external   on   _WinMain@16”的LNK2001错误信息。
3.使用/MD选项编译时,既然所有的运行库都被保留在动态链接库之内,源文件中对“func”的引用,在目标文件里即对“__imp__func”   的引用。如果试图使用静态LIBC.LIB或LIBCMT.LIB进行连接,将在__imp__func上发生LNK2001;如果不使用/MD选项编译,在使用MSVCxx.LIB连接时也会发生LNK2001。   
4.使用/ML选项编译时,如用LIBCMT.LIB链接会在_errno上发生LNK2001。 
5.当编译调试版的应用程序时,如果采用发行版模态库进行连接也会产生LNK2001;同样,使用调试版模态库连接发行版应用程序时也会产生相同的问题。   
6.不同版本的库和编译器的混合使用也能产生问题,因为新版的库里可能包含早先的版本没有的符号和说明。   
7.在不同的模块使用内联和非内联的编译选项能够导致LNK2001。如果创建C++库时打开了函数内联(/Ob1或/Ob2),但是在描述该函数的相应头文件里却关闭了函数内联(没有inline关键字),这时将得到该错误信息。为避免该问题的发生,应该在相应的头文件中用inline关键字标志内联函数。   

8.不正确的/SUBSYSTEM或/ENTRY设置也能导致LNK2001。


其实,产生LNK2001的原因还有很多,以上的原因只是一部分而已,对初 学者来说这些就够理解一阵子了。但是,分析错误原因的目的是为了避免错误的发生LNK2001错误虽然比较困难,但是只要注意到了上述问题,还是能够避免和予以解决的。
### VS中解决 error LNK2001 无法解析外部符号 WinMain 的问题 在使用 Visual Studio 进行开发时,如果遇到 `error LNK2001: 无法解析外部符号 _WinMain` 报错,通常是因为项目配置与实际代码不匹配导致的。以下是详细的解决方案: #### 1. 确认项目类型 `WinMain` 是 Windows 应用程序的入口点函数,而不是控制台应用程序的 `main` 函数。如果项目配置为 Windows 应用程序,但代码中没有定义 `WinMain` 函数,则会触发此错误。需要确保项目的配置与代码一致。 - 如果项目是 **Windows 应用程序**,则需要定义 `WinMain` 函数: ```cpp #include <windows.h> int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 应用程序逻辑 return 0; } ``` - 如果项目是 **控制台应用程序**,则需要将入口点改为 `main` 函数,并修改项目设置以支持控制台应用。 #### 2. 修改项目配置 通过调整项目属性来匹配正确的入口点函数。 - 右键点击项目名称,选择 **属性**。 - 在左侧导航栏中选择 **链接器 -> 系统**。 - 将 **子系统** 设置为 `Windows (/SUBSYSTEM:WINDOWS)` 或 `Console (/SUBSYSTEM:CONSOLE)`,具体取决于项目类型[^1]。 - 如果需要手动指定入口点,可以在 **链接器 -> 高级** 中设置 **入口点** 为 `WinMainCRTStartup` 或 `mainCRTStartup`,根据项目类型选择合适的值。 #### 3. 检查预处理器定义 有时,预处理器定义可能会影响项目的入口点函数。 - 右键点击项目名称,选择 **属性**。 - 在左侧导航栏中选择 **C/C++ -> 预处理器**。 - 确保没有多余的宏定义干扰项目类型。例如,对于控制台应用程序,可以添加 `_CONSOLE` 宏定义[^1]。 #### 4. 检查库文件是否正确 如果项目依赖于某些外部库,但这些库的版本或配置不正确,也可能导致此错误。 - 确保所有使用的库文件与当前项目的架构(如 x86 或 x64)和配置(如 Debug 或 Release)一致[^2]。 - 在 **链接器 -> 输入** 中检查是否正确引用了所需的库文件。 #### 5. 清理并重新构建项目 在修改配置后,建议清理并重新构建项目以确保更改生效。 - 在菜单栏中选择 **生成 -> 清理解决方案**。 - 然后选择 **生成 -> 重新生成解决方案**。 --- ### 示例代码:定义 WinMain 函数 如果项目是 Windows 应用程序,以下是一个简单的 `WinMain` 函数实现示例: ```cpp #include <windows.h> #include <tchar.h> LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { const TCHAR className[] = _T("SampleWindowClass"); WNDCLASS wc = {}; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.lpszClassName = className; if (!RegisterClass(&wc)) { MessageBox(NULL, _T("窗口类注册失败"), _T("错误"), MB_OK | MB_ICONERROR); return 0; } HWND hwnd = CreateWindow(className, _T("示例窗口"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL); if (!hwnd) { MessageBox(NULL, _T("窗口创建失败"), _T("错误"), MB_OK | MB_ICONERROR); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); MSG msg = {}; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } ``` --- ### 注意事项 - 如果项目是控制台应用程序,但错误提示为 `WinMain`,则可能是项目配置错误,需将子系统改为 `Console`。 - 如果项目是 Windows 应用程序,但未定义 `WinMain` 函数,则需要补充该函数实现。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值