编译全攻略-编译器处理及LNK错误的解决方法(2)

http://www.donews.net/xzwenlan/archive/2004/12/23/ 211668.aspx

  这就是我所遇到过的LNK2005错误的几种情况,肯定还有其他的情况也可能造成这种错误,所以我不希望你在看完这篇文章以后,再遇到LNK2005错误时候,不动脑筋的想对号入座的排除错误。编程的过程就是一个思考的过程,所以还是多多开动你的头脑,那样收获会更多!

  该问题有两种解决方法。第一种方法是强制链接器按照正确的顺序链接库。第二种方法是由您亲自查找导致问题的模块并纠正它。

  注意:下列步骤基于 Visual C++ 6.0 进行。

  1. 在“项目”菜单上,单击“设置”。

  2. 在“项目设置”对话框的“以下项目的设置”视图中,单击以选中出现链接错误的项目配置。

  3. 在“链接”选项卡上,单击以选中“类别”组合框中的“输入”。

  4. 在“忽略库”框中,插入库名(例如,Nafxcwd.lib;Libcmtd.lib)。

  注意:等效的链接器命令行是:/NOD:<library name>。

  5. 在“对象/库模块”框中,插入库名。必须确保这些库按顺序列出,而且是行中的前两个库(例如,Nafxcwd.lib 和 Libcmtd.lib)。

  要在 Visual C++ .NET 中设置该选项,请阅读“设置 Visual C++ 项目属性”联机帮助主题。

  解决方案二:找到并纠正出现问题的模块

  < type=text/java>loadTOCNode(2, 'resolution'); 要查看当前的库链接顺序,请按照下列步骤操作:

  1. 在“项目”菜单上,单击“设置”。

  2. 在“项目设置”对话框的“以下项目的设置”视图中,单击以选中出现链接错误的项目配置。

  3. 在“链接”选项卡上的“项目选项”框中键入 /verbose:lib。

  4. 重新生成项目。在链接过程中,这些库将在输出窗口中列出。

  ---------------------------------------------

  以上出现的错误是VC的BUG即是固有的错误,时有发生。解决如下:

  如果下面的不成 请自行上摆渡搜索相关知识,内容丰富,屡试不爽。

  error LNK2001: unresolved external symbol _main解决办法

  解决外部符号错误:_main,_WinMain@16,__beginthreadex )

  在创建MFC项目时, 不使用MFC AppWizard向导, 如果没有设置好项目参数,就会在编译时产生很多连接错误, 如error LNK2001错误, 典型的错误提示有:

  libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main

  LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16

  msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16

  nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex

  nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex n

  1. Windows子系统设置错误, 提示:

  libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main

  Windows项目要使用Windows子系统, 而不是Console, 可以这样设置:

  [Project] --> [Settings] --> 选择"Link"属性页,

  在Project Options中将/subsystem:console改成/subsystem:windows

  2. Console子系统设置错误, 提示:

  LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16

  控制台项目要使用Console子系统, 而不是Windows, 设置:

  [Project] --> [Settings] --> 选择"Link"属性页,

  在Project Options中将/subsystem:windows改成/subsystem:console

  3. 程序入口设置错误, 提示:

  msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16

  通常, MFC项目的程序入口函数是WinMain, 如果编译项目的Unicode版本, 程序入口必须改为wWinMainCRTStartup, 所以需要重新设置程序入口:

  [Project] --> [Settings] --> 选择"Link"属性页,

  在Category中选择Output,

  再在Entry-point symbol中填入wWinMainCRTStartup, 即可

  4. 线程运行时库设置错误, 提示: @: kAF n

  nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex

  nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex

  这是因为MFC要使用多线程时库, 需要更改设置:

  [Project] --> [Settings] --> 选择"C/C++"属性页, ')

  在Category中选择Code Generation,

  再在Use run-time library中选择Debug Multithreaded或者multithreaded

  咸鱼游侠(75374355) 12:11:11

  其中,

  Single-Threaded 单线程静态链接库(release版本)

  Multithreaded 多线程静态链接库(release版本)

  multithreaded DLL 多线程动态链接库(release版本)

  Debug Single-Threaded 单线程静态链接库(debug版本)

  Debug Multithreaded 多线程静态链接库(debug版本)

  Debug Multithreaded DLL 多线程动态链接库(debug版本)

  单线程: 不需要多线程调用时, 多用在DOS环境下

  多线程: 可以并发运行

  静态库: 直接将库与程序Link, 可以脱离MFC库运行

  动态库: 需要相应的DLL动态库, 程序才能运行

 

release版本: 正式发布时使用

  debug版本: 调试阶段使用

  vc中编译、运行程序的小知识点

  1、run-time library

  run-time library是编译器提供的标准库,提供一些基本的库函数和系统调用。

  我们一般使用的run-time library是c run-time libraries。当然也有standard c++ libraries。

  c run-time libraries实现ansi c的标准库。vc安装目录的crt目录有c run-time库的大部分源代码。

  c run-time libraries有静态库版本,l?)h%we教xp也有动态链接库版本;有单线程版本,也有多线程版本;还有调试和非调试版本。

  可以在"project"-"settings"-"c/c++"-"code generation"中选择run-time library的版本。

  动态链接库版本:

  /md multithreaded dll 使用导入库msvcrt.lib

  /mdd debug multithreaded dll 使用导入库msvcrtd.lib

  静态库版本:

  /ml single-threaded 使用静态库libc.lib

  /mld debug single-threaded 使用静态库libcd.lib

  /mt multithreaded 使用静态库libcmt.lib

  /mtd debug multithreaded 使用静态库libcmtd.lib

  c run-time library的标准io部分与操作系统的关系很密切,

  vtf无育网软im-hjb教2|x

  e软v8,|*`:ycs在windows上,crt的io部分代码只是一个包装,底层要用到操作系统内核kernel32.dll中的函数,在编译时使用导入库kernel32.lib。这也就是为什么在嵌入式环境中,我们一般不能直接使用c标准库。

  在linux环境当然也有c标准库,例如:

  ld -o output /lib/crt0.o hello.o -lc

  参数"-lc"就是在引用c标准库libc.a。猜一猜"-lm"引用哪个库文件?

  2、常见的编译参数

  vc建立项目时总会定义"win32"。控制台程序会定义"_console",否则会定义"_windows"。debug版定义"_debug",release版定义"ndebug"

  与mfc dll有关的编译常数包括:

  _windll 表示要做一个用到mfc的dll

  _usrdll 表示做一个用户dll(相对mfc扩展dll而言)

  _afxdll 表示使用mfc动态链接库

  _afxext 表示要做一个mfc扩展dll

  所以:

  regular, statically linked to mfc _windll,_usrdll

  regular, using the shared mfc dll _windll,_usrdll,_afxdll

  extension dll _windll,_afxdll,_afxext

  cl.exe编译所有源文件,

  jv#gxh{网%njt*提b6o%理mkf管link.exe链接exe和dll,lib.exe产生静态库。

  3、subsystem和可执行文件的启动

  link的时候需要指定/subsystem,这个链接选项告诉windows如何运行可执行文件。

  控制台程序是/subsystem:"console"

  其它程序一般都是/subsystem:"windows "

  将 subsystem 选成"console"后,windows在进入可执行文件的代码前(如maincrtstartup),就会产生一个控制台窗口。

  如果选择"windows",操作系统就不产生console窗口,该类型应用程序的窗口由用户自己创建。

  可执行文件都有一个entry point,link时可以用/entry指定。缺省情况下,如果subsystem是“console”,entry point是 maincrtstartup(ansi)或wmaincrtstartuup(unicode),即:

  /subsystem:"console" /entry:"maincrtstartup" (ansi)

  /subsystem:"console" /entry:"wmaincrtstartuup" (unicode)

  maincrtstartup 或 wmaincrtstartuup 会调用main或wmain。

  值得一提的是,在进入应用程序的entry point前,windows的装载器已经做过c变量的初始化,o8x"*+wq1u有初值的全局变量拥有了它们的初值,没有初值的变量被设为0。

  如果subsystem是“windows”,entry point是winmain(ansi)或wwinmain(uincode),即:

  /subsystem:"windows" /entry:"winmaincrtstartup" (ansi)

  /sbusystem:"windows" /entry:"wwinmaincrtstartup" (uincode)

  winmaincrtstartup 或 wwinmaincrtstartup 会调用 winmain 或 wwinmain。

  如果使用mfc框架,winmain也会被埋藏在mfc库中(appmodul.cpp):

  extern "c" int winapi

  _twinmain(hinstance hinstance, hinstance hprevinstance,

  lptstr lpcmdline, int ncmdshow)

  {

  // call shared/exported winmain

  return afxwinmain(hinstance, hprevinstance, lpcmdline, ncmdshow);

  }

  "_t"是一个宏,

  g+za)?h{vx.x_i网@

  v,1+垠y络mvv网crky供3qm对于ansi版本,"_twinmain"就是"winmain";对于uincode版本,"_twinmain"就是"wwinmain"。

  全局c++对象的构造函数是在什么地方调用的?答案是在进入应用程序的entry point后,在调用main函数前的初始化操作中。所以mfc的theapp的构造函数是在_twinmain之前调用的。

  4、不显示console窗口的console程序

  在默认情况下/subsystem 和/entry开关是匹配的,也就是:

  "console"对应"maincrtstartup"或者"wmaincrtstartup"

  "windows"对应"winmain"或者"wwinmain"

  我们可以通过手动修改的方法使他们不匹配。例如:

  #i nclude "windows.h"

  #pragma comment( linker, "/subsystem:/"windows/" /entry:/"maincrtstartup/"" ) // 设置入口地址

  void main(void)

  {

  messagebox(null, "hello", "notice", mb_ok);

  }

  这个console程序就不会显示console窗口。如果选/mld的话,这个程序只需要链接libcd.lib user32.lib kernel32.lib。

你可能感兴趣的:(编译全攻略-编译器处理及LNK错误的解决方法(2))