为什么预编译头(Precompiled Header)能够提高编译速度?
上一篇博客我解释了“为什么可以引用未包含的头文件内容?”,这也让我想起了另外一个问题:“为什么预编译头(Precompiled Header)能够提高编译速度?”。既然要刨根问底,不妨再解释一下这个问题。其实呢,只要理解“编译 - 链接”这两个步骤各自的作用和一般编译器提高编译速度的方式,那这个问题是小菜一碟啊。
上一篇博客我解释了“为什么可以引用未包含的头文件内容?”,这也让我想起了另外一个问题:“为什么预编译头(Precompiled Header)能够提高编译速度?”。既然要刨根问底,不妨再解释一下这个问题。其实呢,只要理解“编译 - 链接”这两个步骤各自的作用和一般编译器提高编译速度的方式,那这个问题是小菜一碟啊。
缘起
最近几天奉老大之命学习研究了一下VCF和VCFBuilder。我在修改编译错误的时候发现有些头文件里面引用了其他头文件里面的类,但是在该头文件里面有没有引入任何其他头文件。编译的时候也没有提示这个错误,按照我的惯性思维,这很不可思议啊!这也让我想起了VC编译环境提供的预编译头StdAfx.h也是这个现象,当时就很纳闷,可是没仔细想。这次又碰到了,忍不住想弄个明白,问了几个大虾,没有答案。那就自己来吧。
让树状控件显示展开和折叠的按钮其实是很简单的,把 Style 设置成TVS_HASBUTTONS就可以了。不过你可能会发现根节点却没有展开折叠按钮,咋回事呢?折腾半天也没作用,还是看看MSDN的文档吧。
TVS_HASBUTTONS
Displays plus (+) and minus (-) buttons next to parent items. The user clicks the buttons to expand or collapse a parent item’s list of child items. To include buttons with items at the root of the tree view, TVS_LINESATROOT must also be specified.
这里说的解析命令行参数,并不是说类似getopt的解析函数,而是说win平台的命令行参数是按什么规则传入程序的。前两天我写了个命令行的程序,程序对根目录的处理总是有问题。经过跟踪,发现当输入参数是(”D:\”)的时候,实际程序读到的参数是(D:”)。在路径的两端加上引号,是为了让路径名称中出现空格的时候不会作为参数分隔符处理。可是显然最后一个引号被\转移为 ” 了。
求助于MSDN,终于找到了命令行解析的规则,原文链接:http://msdn2.microsoft.com/en-us/library/aa243471.aspx。这里我做一下翻译:
这里有几个例子,一看就明白了:
| Command-Line Input | argv[1] | argv[2] | argv[3] |
| “a b c” d e | a b c | d | e |
| “ab\”c” “\\” d | ab”c | \ | d |
| a\\\b d”e f”g h | a\\\b | de fg | h |
| a\\\”b c d | a\”b | c | d |
| a\\\\”b c” d e | a\\b c | d | e |
用makefile做好了一个工程,不同的模块源代码将会被置于不同的文件夹下,而编译后往往也都只是生成在当前编译的目录下。发布的时候就有点麻烦了,比较笨拙的方法就是,一个个的拷贝出来然后再进行打包。这样显然非常繁琐,如果工程的规模较大,这将是一件非常枯燥的事情。如果把这个枯燥的事情变得自动化是不是比较美好呢?
嘿,这其实是很简单的,你只需要在每一个模块生成的命令的后面利用xcopy来拷贝到目的路径就可以了。这个命令是这么写的:
有了这句话,就会把当前编译文件夹下生成的所有DLL都拷贝到目的路径下。下面我来解释一下他们含义:
看了这个解释是不是已经能够透彻的理解啦?:-)
当然如果要让这个发布流程都自动化,这样简单的尝试显然是不够的,日后再慢慢探讨吧。
问题:Runtime Error R6034
在VS2005编译环境下,用makefile编译的程序爆出了一个可恶的Runtime Error。
错误如下图:
提示信息是:
Runtime Error!
R6034
An application has made an attempt to load the C runtime library incorrectly. Please contact the application’s support team for more information.
无法正常载入 C runtime library。
问题追因
程序生成之后直接执行是没有问题的,而打包后的程序却有问题,看来应该是缺少了什么文件。于是我对编译程序生成的文件一个个删除,并查看检查程序的运行情况。在$(APP).exe.manifest被文件删除之后,R6034现身了,看来罪魁祸首就是它了。
我又在MSDN上搜索R6034,得到了这个Error描述的:
An application has made an attempt to load the C runtime library without using a manifest. This is an unsupported way to load Visual C++ DLLs. You need to modify your application to build with a manifest.
这么以来更确认了出现这个问题的原因:缺少了manifest,程序因此无法正常载入C runtime library。
解决办法
解决方法有两个:
嵌入到可执行文件的方法是,需要在生成exe之后在执行下面的命令:
mt.exe –manifest $(APP).exe.manifest -outputresource:$(APP).exe;1
编译DLL的话,有一点点小区别的。
mt.exe –manifest $(LIB).dll.manifest -outputresource:$(LIB).dll;2
后话
VC2005搞出个这玩意有什么好处?