vc 编译的那些事儿
来源:互联网 发布:淘宝店关了怎么重新开 编辑:程序博客网 时间:2024/05/14 11:34
vc8.0设置依赖库
vc8.0设置依赖库的办法是 项目 -> **(项目名)属性 -> 链接器节点 -> 输入 -> 附加依赖项
另外还可以使用pragma comment语句设置依赖库
#pragma comment(lib, "yourlib.lib") //设置依赖库
#pragma comment(linker, "LIBPATH:YourDir") //设置目录
当出现类似以下链接错误时,可能是由于依赖库设置不正确引起
错误 1 error LNK2019: 无法解析的外部符号 ***, 该符号在函数 "public: __cdecl ***::***(void)" (??1CSMS@@QAA@XZ) 中被引用 ***.obj
大家都知道现在的vs2010马上就要推出了,但是还有很多人喜欢使用vc6进行编程,原因很简单,就是因为用vc6编译的程序,依赖的库msvcrt42。mfc42等在winxp之后的版本都自动集成了,所以,用户使用时像绿色软件一样。但是vc6早已是过时的开发环境了,他的界面效果不好,语法检测不严格。如果我们在用vs2003之后的所有开发环境开发出的程序也像vc6一样,不需要安装任何运行时库就可以绿色使用那该是多么幸福的事呀。下面我就介绍三种不依赖这些库的方法。
在一个纯win32程序里,假如我们只使用标准的API,那么编译出来的程序依然需要运行时的库,原因很简单,因为windows默认的winmain函数是由运行时函数startup调用的,所以在这种情况下必然会用到msvcrt80、90的库。解决的办法是
方法一:
修改项目属性-》c/C++->代码生成->运行时库 (将调试dll或dll修改为相应版本的非dll),这种方法就相当于将动态连接修改为静态链接。当然了这么做会使程序本身体积变大。
方法二:
利用宏#pragma comment(linker,"/entry:startup")
这个宏修改了函数的入口点函数,这样,windows加载进程时就不会先进入crt函数了。
以上两种方法都存在一些局限性。比如方法二中的代码必须不能使用任何crt函数,而面对mfc编写的程序两种方法就都无能为力了,下面介绍一种万能的方法:
方法三:
通过使用WDK或者DDK对程序进行编译。驱动编译的优点是我们可以指定所有的链接lib库,通常情况大家都会选择系统使用的库。而如果是mfc的类库在vc8或vc9中是根本不能自由选择的,编译都是设置死的。而采用驱动编译,就可以将这些库统统修改为mfc42.dll的依赖,这样就不存在高级版本静态链接和打包运行库的痛苦了。当然了采用这种方法时,一些vc6没有带的高级的方法是调用不了的。所以,其实也都或多或少的存在些不足。
VS2005链接问题: LNK2005错误 :error LNK2005: _free 已经在 libcmtd.lib(dbgheap.obj) 中定义
以前经常遇到这个警告信息,因为运行并没有什么问题,所以也没深究。但是耿耿于怀那个“ 0 个错误,0 个警告”的成功提示,在网上搜了一下。原来问题出在默认库的引用选择上。
VS2008,项目——属性——配置属性——C/C++——代码生成:他有/MT,/MTd,/Md,/MDd四个选项,你必须让所有使用的库都使 用相同的配置,否则就会有相应的提示,甚至可能会出现无法解析的函数。有时我们使用的库不是自己可以控制的,那么就只能把工程属性设置成河你使用的库相同 的选项。
错误 1 error LNK2005: _free 已经在 libcmtd.lib(dbgheap.obj) 中定义 MSVCRT.lib
错误 2 error LNK2005: _malloc 已经在 libcmtd.lib(dbgheap.obj) 中定义 MSVCRT.lib
.....
如果有一堆的重定义错误发生在同一个lib中,而且跟它冲突的也是同一个lib,那么这个两个lib的功能应该是一样的,可以2选一,只要在“忽略特定的库”内填入需要忽略的库。
项目属性-配置属性-链接器-输入-忽略特定的库:libcmtd.lib
项目属性-配置属性-常规-MFC的使用:在共享 DLL 中使用 MFC
MSVCRT.lib 和libcmt.lib的冲突还是比较常见的。
从错误信息可以看出是msvcrt.lib和libcmt.lib库中重复定义了__isctype等符号。为什么会出现这样的问题呢?这就要从这两个库的作用说起了。
msvcrt.lib是VC中的Multithreaded DLL 版本的C运行时库,而libcmt.lib是Multithreaded的运行时库。在同一个项目中,所有的源文件必须链接相同的C运行时库。如果某一文 件用了Multithreaded DLL版本,而其他文件用了Single-Threaded或者Multithreaded版本的库,也就是说用了不同的库,就会导致这个警告的出现。
告警信息的意思我们明白之后,就要找造成这个问题的原因了。在项目设置中我们可以看到当前项目使用的是Multithreaded非DLL版本的运 行时库,这说明项目中还有其他文件用到了不是这个版本的运行时库。很显然,就是openssl的静态库。查看openssl中ms下的nt.mak,我们 可以发现静态库版本中openssl使用编译开关/MD进行编译的,也就是说openssl静态库是默认用的Multithreaded DLL 版本的C运行时库。
原因找到了。那么解决方法,很明显有两个。总之就是将两个项目的运行时库统一。
简单的方式就是将项目的动态库修改为使用Multithreaded DLL 版本的C运行时库即可。
某些情况下你的项目可能不能改变当前的运行时库,你可以将openssl的nt.mak中的/MD开关修改为/MT然后重新编译openssl静态库就可以了。
默认库“library”与其他库的使用冲突;请使用 /NODEFAULTLIB:library LNK4098 的解决办法
您试图与不兼容的库链接。
注意
运行时库现在包含可防止混合不同类型的指令。如果试图在同一个程序中使用不同类型的运行时库或使用调试和非调试版本的运行时库,则将收到此警告。例如,如 果编译一个文件以使用一种运行时库,而编译另一个文件以使用另一种运行时库(例如单线程运行时库对多线程运行时库),并试图链接它们,则将得到此警告。应 将所有源文件编译为使用同一个运行时库。有关更多信息,请参见使用运行时库(/MD、/MT 和 /LD)编译器选项。
可以使用链接器的 /VERBOSE:LIB 开关来确定链接器搜索的库。如果收到 LNK4098,并想创建使用如单线程、非调试运行时库的可执行文件,请使用 /VERBOSE:LIB 选项确定链接器搜索的库。链接器作为搜索的库输出的应是 LIBC.lib,而非 LIBCMT.lib、MSVCRT.lib、LIBCD.lib、LIBCMTD.lib 和 MSVCRTD.lib。对每个要忽略的库可以使用 /NODEFAULTLIB,以通知链接器忽略错误的运行时库。
下表显示根据要使用的运行时库应忽略的库。
若要使用第一行运行时库 请忽略第2行的这些库
单线程 (libc.lib)
libcmt.lib、msvcrt.lib、libcd.lib、libcmtd.lib、msvcrtd.lib
多线程 (libcmt.lib)
libc.lib、msvcrt.lib、libcd.lib、libcmtd.lib、msvcrtd.lib
使用 DLL 的多线程 (msvcrt.lib)
libc.lib、libcmt.lib、libcd.lib、libcmtd.lib、msvcrtd.lib
调试单线程 (libcd.lib)
libc.lib、libcmt.lib、msvcrt.lib、libcmtd.lib、msvcrtd.lib
调试多线程 (libcmtd.lib)
libc.lib、libcmt.lib、msvcrt.lib、libcd.lib、msvcrtd.lib
使用 DLL 的调试多线程 (msvcrtd.lib)
libc.lib、libcmt.lib、msvcrt.lib、libcd.lib、libcmtd.lib
例如,如果收到此警告,并希望创建使用非调试、单线程版本的运行时库的可执行文件,可以将下列选项与链接器一起使用:
/NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:libcd.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrtd.lib
写进vs205\vs2008中 用分号隔开即可
======================================================================================================================
C2005编译出来的程序文件,采用了manifest方式来指定dll文件。对于win98、win2000系统,把exe文件和VC的 dll连接库放到一起就成了。对于winxp、win2003系统就要麻烦的多了,VC的连接库默认是被放到了winsxs目录下,结果造成在这些系统上,直接拷贝exe文件,往往是不能运行(找不到msvcr80.dll、mfc80.dll文件等),或者在事件日志中报错。
解决方式:
方式一、在目标系统上安装2005版vcredist_x86.exe。
方式二、直接拷贝VS8目录下的VC \ redist \ x86 \ 目录下的 Microsoft.VC80.MFC、Microsoft.VC80.CRT、Microsoft.VC80.MFCLOC几个文件夹,到exe所在的目录下,目录结构如下:
.\myapp.exe
.\myapp.dll
.\Microsoft.VC80.CRT\
.\Microsoft.VC80.MFC\
.\Microsoft.VC80.MFC\Microsoft.VC80.MFCLOC\
然后修改Microsoft.VC80.MFCLOC目录下的Microsoft.VC80.MFCLOC.manifest文件,将其中的version="8.0.50727.42",修改为version="8.0.50608.0"。
方式二的目录结构,在xp和2003下是没有问题的,但是在win98/win2000中,因为exe和dll不在同一目录下,就会出现找不到dll的问题。
有什么更好的解决呢?呵呵,国外的一个大牛(http://blog.kalmbachnet.de)找到一绝招:
方式三、
1、首先编译myapp.exe的时候,在配置中,选择生成单独的manifest文件,如:myapp.exe.manifest。
2、将myapp.exe、myapp.exe.manifest拷贝到一个目录下
3、将Microsoft.VC80.MFC、Microsoft.VC80.CRT、Microsoft.VC80.MFCLOC几个目录下的文件,都拷贝到myapp.exe所在的目录下。
4、将Microsoft.VC80.MFCLOC.manifest文件中的version="8.0.50727.42",修改为version="8.0.50608.0"。
5、编辑myapp.exe目录下的所有 .manifest文件,将文件中的publicKey键值删除,一般是publicKeyToken="1fc8b3b9a1e18e3b"
6、然后运行myapp.exe看看,嗯。
另,其他解决方法:
最近用vc2005写了一个程序,拷贝到其它机器上运行时,提示“由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题。”。
觉得很奇怪,依赖的dll都有在,怎么会提示错误呢。马上上网用这个错误查了一下,大多数人说是编译选项的问题,以下是摘自http://bbs.mscommunity.com/forums/ShowThread.aspx?PostID=52760的解答:
在项目属性-〉配置属性-〉c/c++ -〉代码生成里,有一个运行时库,.net 05 的默认选项是 多线程DLL,把他改成多线程即可。
后来我花了一些时间测试,发现也可以不用修改编译选项,只要将Program Files\Microsoft Visual Studio 8\VC\redist下相应平台的Microsoft.VC80.MFC.manifest和Microsoft.VC80.CRT.manifest拷贝到应用程序目录即可。如果你还用到了atl库,则还要Microsoft.VC80.ATL.manifest。
总结:解决这个问题目前我所知道的有两种方法,
1,修改项目属性,静态链接mfc库(静态链接时,会自动修改上面提到的多线程DLL为多线程)。
2,带上Microsoft.VC80.MFC.manifest和Microsoft.VC80.CRT.manifest。
其他人回复:
=============================================================================================
首先感谢这位几仁兄的几篇博客:
http://hi.baidu.com/fairysky/blog/item/130dda13db7b050a5aaf53be.html
http://hi.baidu.com/fairysky/blog/item/e7a8366dbaa735f3431694c8.html
http://www.cppblog.com/lf426/archive/2008/04/12/46885.aspx
时间缘由:
有时间再来整理:有点凌乱,不好意思。
感谢的XCyber回复:
为什么这么折腾呢?
这样看来,微软发明manifest是错误的,因为大家都为运行库烦恼,真的还不如VC6,这可能吗?
其实很简单,打开你的vs,创建一个Setup and Development下的Setup Project项目,然后添加Merge Module,选择你需要的运行库,最后就是Build,生成的文件与你的程序一起发布就行了;
http://blog.csdn.net/wowolook/article/details/8077153
- vc 编译的那些事儿
- vc 编译的那些事儿
- vc 编译的那些事儿
- VC++的那些事儿
- 编译过程的那些事儿
- VC----MFC文件操作的那些事儿
- 转:理清编译链接的那些事儿
- Java编译那些事儿
- Java编译那些事儿
- linux编译符号那些事儿
- GCC编译时你需要知道的那些事儿
- 明朝的那些事儿
- Oracle 的那些事儿
- 游戏的那些事儿
- 编译器的那些事儿
- 找工作的那些事儿
- 北爱尔兰的那些事儿
- 数组的那些事儿~
- JAVA学习篇--Servlet详解
- wpf 自定义时间编辑控件
- 出现一次,两数
- html之object标签的classid收集
- poj 2247 Humble Numbers
- vc 编译的那些事儿
- C/C++变量在内存中的位置及初始化问题
- HDFS HA架构以及源码引导
- VirtualBox虚拟机下Ubuntu操作系统设置共享文件夹
- 一个独立程序员对自己近九个月工作生活的回顾
- POJ 1185 炮兵阵地(状压dp)
- 《Javascript权威指南》学习笔记之十八:BOM新成就(1)--客户端存储数据(Web SQL DataBase实现)
- mysql日志文件查询问题 乐杨俊
- CCA的matlab小实验