﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-绿-文章分类-Compile</title><link>http://www.cppblog.com/MyCBlog/category/18568.html</link><description>希望，是美好的……</description><language>zh-cn</language><lastBuildDate>Sat, 14 Apr 2012 10:42:53 GMT</lastBuildDate><pubDate>Sat, 14 Apr 2012 10:42:53 GMT</pubDate><ttl>60</ttl><item><title>程序生成过程</title><link>http://www.cppblog.com/MyCBlog/articles/170642.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Mon, 09 Apr 2012 10:08:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/170642.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/170642.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/170642.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/170642.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/170642.html</trackback:ping><description><![CDATA[1，执行预处理命令，解析宏定义，进行宏替换<br />2，处理包含文件，将头文件嵌入到原文件中。<br />3，对每个源文件编译，对应生成各自的obj文件。<br />4，对各个obj文件链接，生成exe。<br />在创建dll文件时，有所不同，当所有的obj文件链接之后，会生成一个dll文件。如果连接器检测到dll的源文件中输出了至少一个函数和变量，那么连接器还会生成一个lib文件。这个lib文件很小，只是列出了所有被导出的函数和变量的符号名（符号表）。<br />当所有的obj模块都创建完毕后，链接器将obj合并，产生一个可执行镜像exe，其中有个导入段，这个导入段包含了所有他需要的dll模块的名称。<img src ="http://www.cppblog.com/MyCBlog/aggbug/170642.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-04-09 18:08 <a href="http://www.cppblog.com/MyCBlog/articles/170642.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>构建DLL模块</title><link>http://www.cppblog.com/MyCBlog/articles/165213.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Thu, 09 Feb 2012 05:24:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/165213.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/165213.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/165213.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/165213.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/165213.html</trackback:ping><description><![CDATA[<p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">在创建一个DLL的时候，事实上在创建一组可供一个执行模块（或者其他DLL）调用的模块。一个dll可以到处变量，函数或者C++类，来供其他模块的使用。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">另外，</span><span style=" font-weight:bold; font-size:10.5000pt; font-family:'宋体'; ">在创建DLL的时候，应该首先创建一个头文件来包含想要导出的变量和函数。这个头文件还必须定义导出的函数或者变量所用到的任何符号和数据结构</span><span style="font-size: 10.5pt; font-family: 宋体; ">。DLL的所有源文件，都应该包括这个头文件。另外，我们必须分发这个头文件。这样任何可能需要导入这些函数或者变量的源文件都可以包含该头文件。让DLL的构建者和可执行模块的构建者使用同一个头文件可以使维护更加容易。<br />下面用例子说明：</span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">/*</span><span style="color: #008000; ">*******************<br />MyLib.h<br />*******************</span><span style="color: #008000; ">*/</span><br />#ifdef&nbsp;MYLIBAPI<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">MYLIBAPI&nbsp;should&nbsp;be&nbsp;defined&nbsp;in&nbsp;all&nbsp;of&nbsp;the&nbsp;DLL's&nbsp;source.<br /></span><span style="color: #008000; ">//</span><span style="color: #008000; ">code&nbsp;modules&nbsp;before&nbsp;this&nbsp;header&nbsp;is&nbsp;included.<br /><br /></span><span style="color: #008000; ">//</span><span style="color: #008000; ">All&nbsp;functions/variables&nbsp;are&nbsp;being&nbsp;exported.</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">#else</span><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">This&nbsp;header&nbsp;file&nbsp;is&nbsp;included&nbsp;by&nbsp;an&nbsp;exe&nbsp;source&nbsp;coude&nbsp;moudle.</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">#define</span>&nbsp;MYLIBAPI&nbsp;extern&nbsp;"C"&nbsp;_declspec(dllimport)<br /><span style="color: #0000FF; ">#endif</span><br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">define&nbsp;and&nbsp;data&nbsp;structuree&nbsp;and&nbsp;symbols&nbsp;hear<br /><br /><br /></span><span style="color: #008000; ">//</span><span style="color: #008000; ">define&nbsp;exported&nbsp;variables&nbsp;here.</span><span style="color: #008000; "><br /></span>MYLIBAPI&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;g_nResult;<br /><br />MYLIBAPI&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;add(<span style="color: #0000FF; ">int</span>&nbsp;nleft,<span style="color: #0000FF; ">int</span>&nbsp;nright);</div><span style=" font-size:10.5000pt; font-family:'宋体'; ">在dll的源文件中，都应该包含这个头文件：<br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">/*</span><span style="color: #008000; ">***************<br />MyLibFile1.cpp<br />/***************</span><span style="color: #008000; ">*/</span><br /><br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">include&nbsp;the&nbsp;standard&nbsp;windows&nbsp;and&nbsp;C-Runtime&nbsp;header&nbsp;file&nbsp;here.</span><span style="color: #008000; "><br /></span><br />#include&nbsp;&lt;Windows.h&gt;<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">this&nbsp;dll&nbsp;source&nbsp;code&nbsp;file&nbsp;exports&nbsp;functions&nbsp;and&nbsp;varibales</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">#define</span>&nbsp;MYLIBAPI&nbsp;extern&nbsp;"C"&nbsp;_declspec(dllexport)<br /><br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">include&nbsp;teh&nbsp;exported&nbsp;data&nbsp;structures,symbols,functions,and&nbsp;varibales.</span><span style="color: #008000; "><br /></span><br /><span style="color: #0000FF; ">int</span>&nbsp;g_nResult;<br /><br /><span style="color: #0000FF; ">int</span>&nbsp;Add(<span style="color: #0000FF; ">int</span>&nbsp;nLeft,<span style="color: #0000FF; ">int</span>&nbsp;nRight)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;g_nResult&nbsp;=&nbsp;nLeft&nbsp;+&nbsp;nRight;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;(g_nResult);<br />}<br /><span style="color: #808080; ">///////////////</span><span style="color: #008000; ">//end&nbsp;of&nbsp;the&nbsp;file&nbsp;</span><span style="color: #808080; ">//////////////////////////////</span><span style="color: #008000; ">/</span><span style="color: #808080; "><br /></span></div><div><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="font-size: 10.5pt; ">在编译前面的DLL源文件时候，MYLIBAPI在包含MyLib.h头文件之前，被定义为_declspec（dll&nbsp;export）.如果编译器看到一个变量，函数，或者类，使用_declspec（dllexport）修饰的，那么它就知道应该在生成DLL的模块中导出该变量、函数或者C++类，注意对那些需要被导出的变量和函数，我们必须在头文件中的变量和函数定义前面加上MYLIBAPI标识符。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="font-size: 10.5pt; ">另外要注意，在源文件中，不必在要被导出的变量函数前面加上MYLIBAPI&nbsp;标识符，这里不需要MYLIBAPI&nbsp;标识符的原因在于编译器在解析头文件的时候，会记住导出哪些变量或者函数。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="font-size: 10.5pt; ">我们还会注意到，在MYLIBAPI&nbsp;符号包含有个extern&nbsp;C修饰符，只有在编写C++代码时候，才会使用这个修饰符，在编写C代码的时候，不应该使用该修饰符。C++编译器通常会对函数名和变量进行改编，这在链接的时候，会导致严重的问题。举个例子，假设一个DLL是用C++来写的，而可执行文件使用C写的。在构建DLL的时候，编译器会对函数名进行改编，但在构建可执行文件的时候，编译器不会对函数名进行改编。当连接器试图链接可执行文件时，会发现可执行文件引用了一个不存在的符号并报错。&#8220;extern&nbsp;C&#8221;告诉编译器，不要对变量名和函数名进行改编，这样用C++，C或者任何编程语言编写的可执行模块都可以访问该变量或者函数。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="font-size: 10.5pt; ">现在看到，dll的源文件应该如何使用这个头文件，那么可执行文件的源文件又该如何？可执行文件不应该在包含这个头文件之前定义MYLIBAPI.由于MYLIBAPI未定义，因此头文件会将MYLIBAPI定义为_declspec(dllimport).这样编译器就知道该可执行文件的源文件要从DLL模块中导入一些变量和函数。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="font-size: 10.5pt; ">当microsoft的C++编译器看到用这个修饰符_declspec（dllexport）修饰的变量，类，函数原型，C++类的时候，会在生成的obj文件中嵌入一些额外的信息。当连接器在链接dll的所有obj文件时，会解析这些信息。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="font-weight: bold; font-size: 10.5pt; ">在连接dll的时候，连接器会检测这些与导出的变量，函数，或者类有段的嵌入信息，并生成相应的lib文件。这个lib文件列出了该dll的导出符号，在链接任何可执行模块的时候，只要可执行模块引用了该dll导出的符号，那么这个lib文件当然是必须的。</span><span style="font-size: 10.5pt; ">除了创建这个lib的文件外，连接器还会在生成的dll文件中嵌入一个导出符号表。这个导出段会列出了导出的变量、函数和类的符号名。连接器还会保存相对的虚拟地址，表示每个符号可以再dll模块中的何处找到。<br />我们可以通过微软vs10提供的工具，dumpbin.exe，打开kernel32.dll。下面仅仅列出部分：</span></p></div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->Microsoft&nbsp;(R)&nbsp;COFF/PE&nbsp;Dumper&nbsp;Version&nbsp;10.00.30319.01<br />Copyright&nbsp;(C)&nbsp;Microsoft&nbsp;Corporation.&nbsp;&nbsp;All&nbsp;rights&nbsp;reserved.<br /><br /><br />Dump&nbsp;of&nbsp;file&nbsp;C:\Users\Administrator\Desktop\kernel32.dll<br /><br />File&nbsp;Type:&nbsp;DLL<br /><br />&nbsp;&nbsp;Section&nbsp;contains&nbsp;the&nbsp;following&nbsp;exports&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;KERNEL32.dll<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;00000000&nbsp;characteristics<br />&nbsp;&nbsp;&nbsp;&nbsp;4B1E0840&nbsp;time&nbsp;date&nbsp;stamp&nbsp;Tue&nbsp;Dec&nbsp;08&nbsp;16:03:12&nbsp;2009<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.00&nbsp;version<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;ordinal&nbsp;<span style="color: #0000FF; ">base</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1361&nbsp;number&nbsp;of&nbsp;functions<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1361&nbsp;number&nbsp;of&nbsp;names<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;ordinal&nbsp;hint&nbsp;RVA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AcquireSRWLockExclusive&nbsp;(forwarded&nbsp;to&nbsp;NTDLL.RtlAcquireSRWLockExclusive)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AcquireSRWLockShared&nbsp;(forwarded&nbsp;to&nbsp;NTDLL.RtlAcquireSRWLockShared)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;000490ED&nbsp;ActivateActCtx<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;00039EB8&nbsp;AddAtomA<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;00045D2D&nbsp;AddAtomW<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;000AAC19&nbsp;AddConsoleAliasA<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;000AABAF&nbsp;AddConsoleAliasW<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;0008F914&nbsp;AddIntegrityLabelToBoundaryDescriptor<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;11&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;000855CB&nbsp;AddLocalAlternateComputerNameA<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;12&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;000854E0&nbsp;AddLocalAlternateComputerNameW<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;13&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;0003C0E1&nbsp;AddRefActCtx<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14&nbsp;&nbsp;&nbsp;&nbsp;B&nbsp;00038950&nbsp;AddSIDToBoundaryDescriptor<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;15&nbsp;&nbsp;&nbsp;&nbsp;C&nbsp;0008BFCA&nbsp;AddSecureMemoryCacheCallback<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;16&nbsp;&nbsp;&nbsp;&nbsp;D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddVectoredContinueHandler&nbsp;(forwarded&nbsp;to&nbsp;NTDLL.RtlAddVectoredContinueHandler)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;17&nbsp;&nbsp;&nbsp;&nbsp;E&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddVectoredExceptionHandler&nbsp;(forwarded&nbsp;to&nbsp;NTDLL.RtlAddVectoredExceptionHandler)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8230;&#8230;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8230;&#8230;</div>&nbsp; &nbsp;从中可以 系统看到，符号是按照顺序排列的，RVA这一列中的数值表示一个偏移量，导出的符号位于DLL文件映像的位置。Ordinal这一列是为了和16位版本的操作系统源代码表示兼容而设置的。hint这列是为了提高系统系能而设置的。<br />&nbsp; &nbsp;windows函数连接到可执行文件或者dll文件时，mic希望我们通过符号名来链接。如果使用序号，我们将面临应用程序无法再新版本的os中运行。<font face="宋体"><br /></font><p>&nbsp;</p><img src ="http://www.cppblog.com/MyCBlog/aggbug/165213.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-09 13:24 <a href="http://www.cppblog.com/MyCBlog/articles/165213.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编译器集成工具</title><link>http://www.cppblog.com/MyCBlog/articles/165200.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Wed, 08 Feb 2012 18:16:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/165200.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/165200.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/165200.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/165200.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/165200.html</trackback:ping><description><![CDATA[<div><div><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">通常与编译器集成到一块的有汇编器和预处理器</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">预处理器，可以把存储在不同位置的多个源文件，汇集到一个原文件中。具体讲，如下：</span></p><p style="margin-left:42.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">1.&nbsp;</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">宏处理：预处理器允许用户在源程序中使用宏，宏是经常使用的较长结构的缩写。</span></p><p style="margin-left:42.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; ">2.&nbsp;</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">文件包含：预处理器可以把头文件包含到程序正文中。</span></p><p style="margin-left:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'宋体'; ">汇编器能够产生汇编代码，汇编代码需要交给汇编器做进一步的处理。有些汇编器能够完成汇编器的工作，产生可重定位的代码，交给装配器或者链接编辑器处理。</span></p></div></div><img src ="http://www.cppblog.com/MyCBlog/aggbug/165200.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-09 02:16 <a href="http://www.cppblog.com/MyCBlog/articles/165200.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编译器的各阶段</title><link>http://www.cppblog.com/MyCBlog/articles/165199.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Wed, 08 Feb 2012 18:09:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/165199.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/165199.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/165199.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/165199.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/165199.html</trackback:ping><description><![CDATA[<div><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">词法分析，语法分析，语义分析，中间代码生成，代码优化，代码生成。其中有符号表管理和错误处理，贯穿于整个编译器的过程。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">编译器的一个基本功能是记录源程序中使用的标示符并收集每个标示符相关的各种属性信息。标示符的属性信息表明了该标识符的存储位置、类型、作用域。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">符号表是一个数据结构，每个标示符在符号表中都有一条记录，记录的每个域对应于该标识符的一个属性。这种数据结构允许我们快速的找到每个标识符，并在该记录中快速的存储和检索信息。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">标识符的属性信息由词法分析以后的各个阶段陆续写入符号表。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">每个阶段都可能遇到错误，必须以恰当的方式进行错误处理，使得编译器能够继续运行，以检查出源程序更多的错误。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">词法分析阶段，仅仅分理处源文件中的词语；语法分析，构成语法树；语义分析，对词语进行检测，填写符号表；中间代码生成，可以生成相关的四元式；代码优化阶段，可以有四元式变为三元士；代码生成，则可以形成汇编代码。</span></p></div><img src ="http://www.cppblog.com/MyCBlog/aggbug/165199.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-09 02:09 <a href="http://www.cppblog.com/MyCBlog/articles/165199.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>源程序分析</title><link>http://www.cppblog.com/MyCBlog/articles/165198.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Wed, 08 Feb 2012 17:55:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/165198.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/165198.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/165198.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/165198.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/165198.html</trackback:ping><description><![CDATA[源程序分析，需要经过三个阶段：<br />1，线性分析：从左到右读取字符流，并且把字符后分为多个记号，记号是具有整体含义的字符序列。<br />2，层次分析：每个记号在层析分析中，具有多个嵌套组，每个嵌套组具有整体的含义。<br />3，语义分析：进行语义检查，确保每个组是具有意义组合在一起。<br />具体讲：<br />1，词法分析：也就是线性分析<br />2，语法分析：也就是层次分析，通常用分析树表示。<br />3，语义分析：利用语法分析中的产生的层次结构，识别表达式和语句中的表达式和操作符。<br />4，中间代码生成：生成与机器无关的中间代码。<br />5，代码优化：对中间代码进行优化。<br />6，代码生成：通过汇编，链接，最终生成可执行文件。<img src ="http://www.cppblog.com/MyCBlog/aggbug/165198.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-09 01:55 <a href="http://www.cppblog.com/MyCBlog/articles/165198.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编译的前驱和后继</title><link>http://www.cppblog.com/MyCBlog/articles/165196.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Wed, 08 Feb 2012 17:34:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/165196.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/165196.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/165196.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/165196.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/165196.html</trackback:ping><description><![CDATA[&nbsp; &nbsp;源程序可被分成几个模块，存在几个不同的文件中，把存在于几个不同的模块中文件，汇集为一个源文件的过程，有预处理器完成的，预处理器也可以把称为宏的结构在源文件中替换成响应的语句。经典的生成可执行文件的过程有：预处理，编译，汇编，链接。<img src ="http://www.cppblog.com/MyCBlog/aggbug/165196.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-09 01:34 <a href="http://www.cppblog.com/MyCBlog/articles/165196.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分析--综合模型</title><link>http://www.cppblog.com/MyCBlog/articles/165195.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Wed, 08 Feb 2012 17:29:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/165195.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/165195.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/165195.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/165195.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/165195.html</trackback:ping><description><![CDATA[编译由两部分组成：分析和综合。<br />分析：分析部分将源程序分成一些基本块并形成源程序的中间表示。<br />综合：综合部分将中间部分表示成目标程序。<br />在分析期间，源程序的操作将被确定下来，并被表示成一个称为语法树的分层结构。语法树的每个节点表示一个操作，该节点的子节点表示这个操作的参数。<img src ="http://www.cppblog.com/MyCBlog/aggbug/165195.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-09 01:29 <a href="http://www.cppblog.com/MyCBlog/articles/165195.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编译器</title><link>http://www.cppblog.com/MyCBlog/articles/165194.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Wed, 08 Feb 2012 17:21:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/165194.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/165194.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/165194.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/165194.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/165194.html</trackback:ping><description><![CDATA[将一种语言翻译成另外一种等价的目标语言的程序。<img src ="http://www.cppblog.com/MyCBlog/aggbug/165194.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-09 01:21 <a href="http://www.cppblog.com/MyCBlog/articles/165194.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>纵观dll的构建</title><link>http://www.cppblog.com/MyCBlog/articles/165169.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Wed, 08 Feb 2012 10:15:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/165169.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/165169.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/165169.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/165169.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/165169.html</trackback:ping><description><![CDATA[<div><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">当一个模块（如可执行文件）用到了一个DLL的函数或者变量的时候，会牵涉到许多文件和组件。为了便于讨论，我们将一个dll中导入函数和变量的模块称为&#8220;可执行模块&#8221;，将导出函数和变量一个供其他可执行文件使用的模块成为&#8220;DLL模块&#8221;，dll模块也可以导入一些包含其他dll模块中的函数和变量。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">构建dll,需要以下步骤：</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">1.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">必须创建一个头文件，在其中包含我们想要在DLL中导出的函数原型，结构以符号。为了构建该DLL，dll中的所有源文件需要包含该头文件。</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">2.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">创建C/C++源文件来实现想要在DLL模块中淡出的函数和变量。</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">3.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">当构建dll模块的时候，编译器会对每个源文件进行处理产生一个obj文件，（每个源文件，对应一个obj模块）</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">4.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">当所有的obj模块创建完毕后，连接器会将所有的.obj模块内容合并，产生一个单独的dll映像文件。这个映像文件或者模块，包含dll中所有的二进制代码以及全局/静态变量。为了执行可执行模块快，这个文件时必须的。</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">5.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">如果连接器检测到DLL的源文件输出少了一个函数或者变量，那么连接器还有生成一个lib文件。这个lib文件非常小，这是因为他并不包含任何函数或者变量。她它只是列出了所有被导出的函数和变量的负号名。为了构建可执行模块，这个模块是必须的。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">一旦构建了dll模块，我们就可以通过下列步骤构建可执行模块</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">1.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">在所有的引用了dll的模块，变量，必须包含有dll的开发者所创建的头文件。</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">2.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">创建C++源文件来实现想要的包含在可执行模块的函数和变量。当然，代码可以引用在dll的头文件中的定义的函数和变量。</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">3.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">在构建可执行模块时候，编译器会对每个源文件进行处理并产生一个.obj文件。</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">4.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">当所有的obj都创建完毕后，连接器会将所有的obj模块的内容合并，产生一个单独的可执行文件，这个映像文件包含了可执行文件中的所有二进制代码以及全局静态变量。该可执行文件还包含一个导入段，其中列出了它需要的dll模块的名称。</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">5.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">加载程序先为新的进程创建一个虚拟的地址空间，并将可执行模块映射到新的地址空间中。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">一旦加载程序将可执行模块和所有的dll模块映射到进程的地址空间之后，进程的主线程可以开始执行，这样引用程序就能够运行了。</span></p></div><img src ="http://www.cppblog.com/MyCBlog/aggbug/165169.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-08 18:15 <a href="http://www.cppblog.com/MyCBlog/articles/165169.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>dll和进程的地址空间</title><link>http://www.cppblog.com/MyCBlog/articles/165164.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Wed, 08 Feb 2012 09:14:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/165164.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/165164.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/165164.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/165164.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/165164.html</trackback:ping><description><![CDATA[<div><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">使用动态链接库的理由：</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">1.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">他们扩展了应用程序的特性</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">2.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">简化了项目管理</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">3.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">有助于节省内存</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">4.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">促进资源共享</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">5.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">促进本地化</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">6.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">提供特殊目的。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; text-align:justify; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">在创建dll的时候，我们必须给连接器指定dll开关，这个开关会使得连接器在生成dll文件影响中保存一些与可执行文件略微不同的信息，这样操作系统的加载程序能够将该文件识别为dll，而不会将它识别为应用程序。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; text-align:justify; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">应用程序使用dll函数之前，必须将该dll的文件映像到调用进程的地址空间中。有两种方式：一种是隐式载入链接，另外一种是显示运行时链接。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; text-align:justify; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">一旦dll文件影响到一个进程的地址空间后，进程的所有线程就可以调用dll中的函数了。事实上，该dll几乎完全丧失了dll的身份，进程中的线程来说，该dll中的代码和数据就像一些附加的代码和数据，碰巧放到进程的地址空间中了。当线程调用dll的一个函数时，该函数会在程栈中取得传给他的参数，并使用线程栈存放他需要的局部变量。Dll中函数创建的任何对象都为调用线程或者调用进程所拥有-------dll绝对不会拥有任何对象。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; text-align:justify; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">如果运行同一个可执行文件的多个实例，这些实例就不会共享可执行文件中的全局变量和静态变量。Windows通过使用写时复制机制，保证这一点。Dll中的全局变量和局部变量也是通过完全相同的方法处理的。当一个进程将一个dll文件映射到自己的地址空间中时，系统也会为全局变量和静态变量创建新的实例。</span></p></div><img src ="http://www.cppblog.com/MyCBlog/aggbug/165164.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-08 17:14 <a href="http://www.cppblog.com/MyCBlog/articles/165164.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解析SimpleSection文件</title><link>http://www.cppblog.com/MyCBlog/articles/164996.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Sun, 05 Feb 2012 08:46:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/164996.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/164996.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/164996.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/164996.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/164996.html</trackback:ping><description><![CDATA[程序清单：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">int</span>&nbsp;printf(<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;*&nbsp;format,<img src="http://www.cppblog.com/Images/dot.gif" alt="" />);<br /><span style="color: #0000FF; ">int</span>&nbsp;global_init_var&nbsp;=&nbsp;84;<br /><span style="color: #0000FF; ">int</span>&nbsp;global_uninit_var;<br /><span style="color: #0000FF; ">void</span>&nbsp;fun1(<span style="color: #0000FF; ">int</span>&nbsp;i)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;printf("%d\n",i);<br />}<br /><span style="color: #0000FF; ">int</span>&nbsp;main()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;static_var&nbsp;=&nbsp;85;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;static_var2;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;a&nbsp;=&nbsp;1;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;b;<br />&nbsp;&nbsp;&nbsp;&nbsp;func1(static_var&nbsp;+&nbsp;static_var2&nbsp;+&nbsp;a&nbsp;+&nbsp;b);<br />}</div>编译后生成SimpleSection.0文件，经过objdump -h&nbsp;SimpleSection.0,打开之后，可得如下代码：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->C:\Users\Administrator\Desktop\SimpleSectoin.o:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file&nbsp;format&nbsp;pe-i386<br /><br />Sections:<br />Idx&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VMA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LMA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;off&nbsp;&nbsp;Algn<br />&nbsp;&nbsp;0&nbsp;.text&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00000050&nbsp;&nbsp;00000000&nbsp;&nbsp;00000000&nbsp;&nbsp;00000104&nbsp;&nbsp;2**2<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONTENTS,&nbsp;ALLOC,&nbsp;LOAD,&nbsp;RELOC,&nbsp;READONLY,&nbsp;CODE<br />&nbsp;&nbsp;1&nbsp;.data&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00000008&nbsp;&nbsp;00000000&nbsp;&nbsp;00000000&nbsp;&nbsp;00000154&nbsp;&nbsp;2**2<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONTENTS,&nbsp;ALLOC,&nbsp;LOAD,&nbsp;DATA<br />&nbsp;&nbsp;2&nbsp;.bss&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00000004&nbsp;&nbsp;00000000&nbsp;&nbsp;00000000&nbsp;&nbsp;00000000&nbsp;&nbsp;2**2<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ALLOC<br />&nbsp;&nbsp;3&nbsp;.drectve&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00000024&nbsp;&nbsp;00000000&nbsp;&nbsp;00000000&nbsp;&nbsp;0000015c&nbsp;&nbsp;2**2<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONTENTS,&nbsp;ALLOC,&nbsp;LOAD,&nbsp;DATA<br />&nbsp;&nbsp;4&nbsp;.rdata&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00000004&nbsp;&nbsp;00000000&nbsp;&nbsp;00000000&nbsp;&nbsp;00000180&nbsp;&nbsp;2**2<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONTENTS,&nbsp;ALLOC,&nbsp;LOAD,&nbsp;READONLY,&nbsp;DATA<br />&nbsp;&nbsp;5&nbsp;.eh_frame&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00000058&nbsp;&nbsp;00000000&nbsp;&nbsp;00000000&nbsp;&nbsp;00000184&nbsp;&nbsp;2**2<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONTENTS,&nbsp;ALLOC,&nbsp;LOAD,&nbsp;RELOC,&nbsp;READONLY,&nbsp;DATA<br /><br />C:\Users\Administrator&gt;</div><div>&nbsp;通过代码可知，efl文件除了代码段、数据段之外，还有bss段，drectve段，rdata段，eh_frame段。另外可以看到各个段所具有的属性，size属性，file off属性，contents属性。<br />然后我们分析代码段：通过命令objdump -s -d SimpleSection.o,可得如下命令：<br /><div style="font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-image: initial; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; background-color: #eeeeee; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br />C:\Users\Administrator&gt;objdump&nbsp;-s&nbsp;-d&nbsp;C:\Users\Administrator\Desktop\SimpleSectoin.o<br /><br />C:\Users\Administrator\Desktop\SimpleSectoin.o:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file&nbsp;format&nbsp;pe-i386<br /><br />Contents&nbsp;of&nbsp;section&nbsp;.text:<br />&nbsp;0000&nbsp;5589e583&nbsp;ec188b45&nbsp;08894424&nbsp;04c70424&nbsp;&nbsp;U<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" />E..D$<img src="http://www.cppblog.com/Images/dot.gif" alt="" />$<br />&nbsp;0010&nbsp;00000000&nbsp;e8000000&nbsp;00c9c355&nbsp;89e583e4&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" />..U<img src="http://www.cppblog.com/Images/dot.gif" alt="" />.<br />&nbsp;0020&nbsp;f083ec20&nbsp;e8000000&nbsp;00c74424&nbsp;1c010000&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" />&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" />D$<img src="http://www.cppblog.com/Images/dot.gif" alt="" />.<br />&nbsp;0030&nbsp;008b1504&nbsp;000000a1&nbsp;00000000&nbsp;01d00344&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" />D<br />&nbsp;0040&nbsp;241c0344&nbsp;24188904&nbsp;24e80000&nbsp;0000c9c3&nbsp;&nbsp;$..D$<img src="http://www.cppblog.com/Images/dot.gif" alt="" />$<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" />.<br />Contents&nbsp;of&nbsp;section&nbsp;.data:<br />&nbsp;0000&nbsp;54000000&nbsp;55000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;T<img src="http://www.cppblog.com/Images/dot.gif" alt="" />U<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><br />Contents&nbsp;of&nbsp;section&nbsp;.drectve:<br />&nbsp;0000&nbsp;202d616c&nbsp;69676e63&nbsp;6f6d6d3a&nbsp;225f676c&nbsp;&nbsp;&nbsp;-aligncomm:"_gl<br />&nbsp;0010&nbsp;6f62616c&nbsp;5f756e69&nbsp;6e69745f&nbsp;76617222&nbsp;&nbsp;obal_uninit_var"<br />&nbsp;0020&nbsp;2c320000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;,2..<br />Contents&nbsp;of&nbsp;section&nbsp;.rdata:<br />&nbsp;0000&nbsp;25640a00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%d..<br />Contents&nbsp;of&nbsp;section&nbsp;.eh_frame:<br />&nbsp;0000&nbsp;14000000&nbsp;00000000&nbsp;017a5200&nbsp;017c0801&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" />zR..|..<br />&nbsp;0010&nbsp;1b0c0404&nbsp;88010000&nbsp;1c000000&nbsp;1c000000&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" />.<br />&nbsp;0020&nbsp;04000000&nbsp;1b000000&nbsp;00410e08&nbsp;8502420d&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" />A<img src="http://www.cppblog.com/Images/dot.gif" alt="" />.B.<br />&nbsp;0030&nbsp;0557c50c&nbsp;04040000&nbsp;1c000000&nbsp;3c000000&nbsp;&nbsp;.W<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" />.&lt;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><br />&nbsp;0040&nbsp;1f000000&nbsp;35000000&nbsp;00410e08&nbsp;8502420d&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" />.5<img src="http://www.cppblog.com/Images/dot.gif" alt="" />.A<img src="http://www.cppblog.com/Images/dot.gif" alt="" />.B.<br />&nbsp;0050&nbsp;0571c50c&nbsp;04040000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.q<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><br /><br />Disassembly&nbsp;of&nbsp;section&nbsp;.text:<br /><br />00000000&nbsp;&lt;_fun1&gt;:<br />&nbsp;&nbsp;&nbsp;0:&nbsp;&nbsp;&nbsp;55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;%ebp<br />&nbsp;&nbsp;&nbsp;1:&nbsp;&nbsp;&nbsp;89&nbsp;e5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;%esp,%ebp<br />&nbsp;&nbsp;&nbsp;3:&nbsp;&nbsp;&nbsp;83&nbsp;ec&nbsp;18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sub&nbsp;&nbsp;&nbsp;&nbsp;$0x18,%esp<br />&nbsp;&nbsp;&nbsp;6:&nbsp;&nbsp;&nbsp;8b&nbsp;45&nbsp;08&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;0x8(%ebp),%eax<br />&nbsp;&nbsp;&nbsp;9:&nbsp;&nbsp;&nbsp;89&nbsp;44&nbsp;24&nbsp;04&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;%eax,0x4(%esp)<br />&nbsp;&nbsp;&nbsp;d:&nbsp;&nbsp;&nbsp;c7&nbsp;04&nbsp;24&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;&nbsp;&nbsp;movl&nbsp;&nbsp;&nbsp;$0x0,(%esp)<br />&nbsp;&nbsp;14:&nbsp;&nbsp;&nbsp;e8&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;19&nbsp;&lt;_fun1+0x19&gt;<br />&nbsp;&nbsp;19:&nbsp;&nbsp;&nbsp;c9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leave<br />&nbsp;&nbsp;1a:&nbsp;&nbsp;&nbsp;c3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret<br /><br />0000001b&nbsp;&lt;_main&gt;:<br />&nbsp;&nbsp;1b:&nbsp;&nbsp;&nbsp;55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;%ebp<br />&nbsp;&nbsp;1c:&nbsp;&nbsp;&nbsp;89&nbsp;e5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;%esp,%ebp<br />&nbsp;&nbsp;1e:&nbsp;&nbsp;&nbsp;83&nbsp;e4&nbsp;f0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;&nbsp;&nbsp;&nbsp;$0xfffffff0,%esp<br />&nbsp;&nbsp;21:&nbsp;&nbsp;&nbsp;83&nbsp;ec&nbsp;20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sub&nbsp;&nbsp;&nbsp;&nbsp;$0x20,%esp<br />&nbsp;&nbsp;24:&nbsp;&nbsp;&nbsp;e8&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;29&nbsp;&lt;_main+0xe&gt;<br />&nbsp;&nbsp;29:&nbsp;&nbsp;&nbsp;c7&nbsp;44&nbsp;24&nbsp;1c&nbsp;01&nbsp;00&nbsp;00&nbsp;&nbsp;&nbsp;&nbsp;movl&nbsp;&nbsp;&nbsp;$0x1,0x1c(%esp)<br />&nbsp;&nbsp;30:&nbsp;&nbsp;&nbsp;00<br />&nbsp;&nbsp;31:&nbsp;&nbsp;&nbsp;8b&nbsp;15&nbsp;04&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;0x4,%edx<br />&nbsp;&nbsp;37:&nbsp;&nbsp;&nbsp;a1&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;0x0,%eax<br />&nbsp;&nbsp;3c:&nbsp;&nbsp;&nbsp;01&nbsp;d0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;%edx,%eax<br />&nbsp;&nbsp;3e:&nbsp;&nbsp;&nbsp;03&nbsp;44&nbsp;24&nbsp;1c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;0x1c(%esp),%eax<br />&nbsp;&nbsp;42:&nbsp;&nbsp;&nbsp;03&nbsp;44&nbsp;24&nbsp;18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;0x18(%esp),%eax<br />&nbsp;&nbsp;46:&nbsp;&nbsp;&nbsp;89&nbsp;04&nbsp;24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;%eax,(%esp)<br />&nbsp;&nbsp;49:&nbsp;&nbsp;&nbsp;e8&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;4e&nbsp;&lt;_main+0x33&gt;<br />&nbsp;&nbsp;4e:&nbsp;&nbsp;&nbsp;c9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leave<br />&nbsp;&nbsp;4f:&nbsp;&nbsp;&nbsp;c3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret<br /><br />C:\Users\Administrator&gt;</div>contents of .text,就是我们前面的.text的内容，共有0x5b大小的内容，最左边一列是偏移量，中间四列是十六进制内容，左右边一列是.text的ascII的内容。按照反汇编的内容，可以明显的看到，.text内容里面包含有func1和mian函数的指令。<br />然后看数据段内容：通过命令objdump -x -s -d SimpleSection.o可得如下内容：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br />C:\Users\Administrator&gt;objdump&nbsp;-s&nbsp;-d&nbsp;C:\Users\Administrator\Desktop\SimpleSectoin.o<br /><br />&#8230;&#8230;<br />Contents&nbsp;of&nbsp;section&nbsp;.data:<br />&nbsp;0000&nbsp;54000000&nbsp;55000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;T<img src="http://www.cppblog.com/Images/dot.gif" alt="" />U<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><br />Contents&nbsp;of&nbsp;section&nbsp;.drectve:<br />&nbsp;0000&nbsp;202d616c&nbsp;69676e63&nbsp;6f6d6d3a&nbsp;225f676c&nbsp;&nbsp;&nbsp;-aligncomm:"_gl<br />&nbsp;0010&nbsp;6f62616c&nbsp;5f756e69&nbsp;6e69745f&nbsp;76617222&nbsp;&nbsp;obal_uninit_var"<br />&nbsp;0020&nbsp;2c320000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;,2..<br />Contents&nbsp;of&nbsp;section&nbsp;.rdata:<br />&nbsp;0000&nbsp;25640a00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%d..<br />Contents&nbsp;of&nbsp;section&nbsp;.eh_frame:<br />&nbsp;0000&nbsp;14000000&nbsp;00000000&nbsp;017a5200&nbsp;017c0801&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" />zR..|..<br />&nbsp;0010&nbsp;1b0c0404&nbsp;88010000&nbsp;1c000000&nbsp;1c000000&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" />.<br />&nbsp;0020&nbsp;04000000&nbsp;1b000000&nbsp;00410e08&nbsp;8502420d&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" />A<img src="http://www.cppblog.com/Images/dot.gif" alt="" />.B.<br />&nbsp;0030&nbsp;0557c50c&nbsp;04040000&nbsp;1c000000&nbsp;3c000000&nbsp;&nbsp;.W<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" />.&lt;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><br />&nbsp;0040&nbsp;1f000000&nbsp;35000000&nbsp;00410e08&nbsp;8502420d&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" />.5<img src="http://www.cppblog.com/Images/dot.gif" alt="" />.A<img src="http://www.cppblog.com/Images/dot.gif" alt="" />.B.<br />&nbsp;0050&nbsp;0571c50c&nbsp;04040000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.q<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><img src="http://www.cppblog.com/Images/dot.gif" alt="" /><br /><br />Disassembly&nbsp;of&nbsp;section&nbsp;.text:<br /><br />00000000&nbsp;&lt;_fun1&gt;:<br />&nbsp;&nbsp;&nbsp;0:&nbsp;&nbsp;&nbsp;55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;%ebp<br />&nbsp;&nbsp;&nbsp;1:&nbsp;&nbsp;&nbsp;89&nbsp;e5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;%esp,%ebp<br />&nbsp;&nbsp;&nbsp;3:&nbsp;&nbsp;&nbsp;83&nbsp;ec&nbsp;18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sub&nbsp;&nbsp;&nbsp;&nbsp;$0x18,%esp<br />&nbsp;&nbsp;&nbsp;6:&nbsp;&nbsp;&nbsp;8b&nbsp;45&nbsp;08&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;0x8(%ebp),%eax<br />&nbsp;&nbsp;&nbsp;9:&nbsp;&nbsp;&nbsp;89&nbsp;44&nbsp;24&nbsp;04&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;%eax,0x4(%esp)<br />&nbsp;&nbsp;&nbsp;d:&nbsp;&nbsp;&nbsp;c7&nbsp;04&nbsp;24&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;&nbsp;&nbsp;movl&nbsp;&nbsp;&nbsp;$0x0,(%esp)<br />&nbsp;&nbsp;14:&nbsp;&nbsp;&nbsp;e8&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;19&nbsp;&lt;_fun1+0x19&gt;<br />&nbsp;&nbsp;19:&nbsp;&nbsp;&nbsp;c9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leave<br />&nbsp;&nbsp;1a:&nbsp;&nbsp;&nbsp;c3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret<br /><br />0000001b&nbsp;&lt;_main&gt;:<br />&nbsp;&nbsp;1b:&nbsp;&nbsp;&nbsp;55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;%ebp<br />&nbsp;&nbsp;1c:&nbsp;&nbsp;&nbsp;89&nbsp;e5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;%esp,%ebp<br />&nbsp;&nbsp;1e:&nbsp;&nbsp;&nbsp;83&nbsp;e4&nbsp;f0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;&nbsp;&nbsp;&nbsp;$0xfffffff0,%esp<br />&nbsp;&nbsp;21:&nbsp;&nbsp;&nbsp;83&nbsp;ec&nbsp;20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sub&nbsp;&nbsp;&nbsp;&nbsp;$0x20,%esp<br />&nbsp;&nbsp;24:&nbsp;&nbsp;&nbsp;e8&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;29&nbsp;&lt;_main+0xe&gt;<br />&nbsp;&nbsp;29:&nbsp;&nbsp;&nbsp;c7&nbsp;44&nbsp;24&nbsp;1c&nbsp;01&nbsp;00&nbsp;00&nbsp;&nbsp;&nbsp;&nbsp;movl&nbsp;&nbsp;&nbsp;$0x1,0x1c(%esp)<br />&nbsp;&nbsp;30:&nbsp;&nbsp;&nbsp;00<br />&nbsp;&nbsp;31:&nbsp;&nbsp;&nbsp;8b&nbsp;15&nbsp;04&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;0x4,%edx<br />&nbsp;&nbsp;37:&nbsp;&nbsp;&nbsp;a1&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;0x0,%eax<br />&nbsp;&nbsp;3c:&nbsp;&nbsp;&nbsp;01&nbsp;d0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;%edx,%eax<br />&nbsp;&nbsp;3e:&nbsp;&nbsp;&nbsp;03&nbsp;44&nbsp;24&nbsp;1c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;0x1c(%esp),%eax<br />&nbsp;&nbsp;42:&nbsp;&nbsp;&nbsp;03&nbsp;44&nbsp;24&nbsp;18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;0x18(%esp),%eax<br />&nbsp;&nbsp;46:&nbsp;&nbsp;&nbsp;89&nbsp;04&nbsp;24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;%eax,(%esp)<br />&nbsp;&nbsp;49:&nbsp;&nbsp;&nbsp;e8&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;4e&nbsp;&lt;_main+0x33&gt;<br />&nbsp;&nbsp;4e:&nbsp;&nbsp;&nbsp;c9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leave<br />&nbsp;&nbsp;4f:&nbsp;&nbsp;&nbsp;c3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret<br /><br />C:\Users\Administrator&gt;</div></div><br />通过上面的解析，可以大致知道，ELF文件的轮廓，<br /><fieldset><legend></legend></fieldset><fieldset><legend></legend></fieldset><img src="http://www.cppblog.com/images/cppblog_com/mycblog/解析SimpleSection1.jpg" border="0" alt="" width="416" height="424" /><img src ="http://www.cppblog.com/MyCBlog/aggbug/164996.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-05 16:46 <a href="http://www.cppblog.com/MyCBlog/articles/164996.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>目标文件解析</title><link>http://www.cppblog.com/MyCBlog/articles/164966.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Sat, 04 Feb 2012 19:49:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/164966.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/164966.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/164966.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/164966.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/164966.html</trackback:ping><description><![CDATA[<p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-weight:bold; font-size:10.5000pt; font-family:'宋体'; ">目标文件格式</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">现在pc流行的可执行文件格式主要是windows平台下的PE（Portable&nbsp;Executable）和Linux的ELF（Executable&nbsp;Linkable&nbsp;Format），他们都是COFF文件的格式的变种。目标文件就是源代码文件编译后但未进行连接的哪些中间文件，他跟可执行文件相似，所以一般跟可执行文件格式一起采用格式存储。在windows平台下，统称PE--COFF文件格式。在linux下，统称为ELF文件。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">不光是可执行文件可以按照可执行文件存储，动态链接库dll和静态链接库lib文件都可以按照可执行文件格式存储。他们在windows下都按照PE--COFF格式存储，LINUX下按照ELF格式存储，静态链接库稍微不同，他是把很多目标文件捆绑为一个文件，在加上一些索引，你可以简单的理解为一个包含很多目标文件的文件包。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">目标文件和可执行文件的格式跟操作系统和编译器密切相关，不同的系统平台下会有不同的格式，但这些格式大同小异，目标文件格式与可执行文件科室的历史几乎是操作系统的发展史。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-weight:bold; font-size:10.5000pt; font-family:'宋体'; ">目标文件内容</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">目标文件中的内容至少有编译后的机器指令代码、数据，没错，除了这些内容以外，目标文件还包括了连接时所需要的一些信息，如符号表，调试信息，字符串。一般的目标文件将这些信息按照不同的属性，以&#8220;节&#8221;的形式存储，有时候也叫做&#8220;段&#8221;，一般都表示一定长度的区域，基本上不加区别。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">程序源代码编译后的机器指令经常被放在代码段里，代码段常用名字有code或者text，全局变量和局部静态变量经常放在数据段，数据段的一般名字叫做data。如图所示：</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><img src="http://www.cppblog.com/images/cppblog_com/mycblog/目标文件解析1.jpg" width="785" height="481" alt="" /><br /></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">假设图的可执行文件格式是elf，从图中可以看到，efl文件的开头是一个文件头，描述文件的属性，包括文件是否可执行，是静态链接还是动态链接以及入口地址（如果是可执行文件）文件头还有个段表。段表其实是一个ie描述文件中各个段的数组。段表描述了文件中各个段在文件中的偏移位置以及段的属性等，从段里面可以看到每个段的所有信息。文件头后米娜就是各个段的内容，比如代码段保存的就是程序的指令，数据段保存就是的程序的敬爱变量。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">对照图来看，一般C语言的编译后执行语句都是机器代码，保存在text段中。已初始化的全局变量和局部变量都保存在data段中；为初始化的全局变量和局部变量一般放在一个叫做bss段里面，但是以为内他们都是0，所以在data段分配空间的时候，并且存放0是没有必要的。程序运行的时候，他们的确是要占内存空间的，并且可执行文件必须记录所有为初始化的全局变量和局部静态变量的大小总和，记为bss段。</span><span style=" font-weight:bold; font-size:10.5000pt; font-family:'宋体'; ">Bss段只是为初始化的全局变量和局部静态变量预留位置而已，</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">他并没有内容，所以文件中不占空间。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">总的来说，程序源代码被编译后主要分成两种段：程序指令和程序数据。代码段属于程序指令，而数据段和bss段属于程序数据。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">数据和指令分段有诸多好处，主要有一下几个方面：</span></p><p style="margin-left:63.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">1.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">一方面程序被加载后，数据和指令分别被映射到两个虚存区。由于数据区域对于进程来说是可读写的，而指令区域对于进程来说，是只读的，所以这两个虚存区域的权限可以被设置为读写与只读。防止程序的指令被有意或者无意改写。</span></p><p style="margin-left:63.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">2.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">另一方面，对于现代CPU来说，他们有着极其强大的缓存体系，有与缓存在现代计算机中地位非常重要，所以程序尽量提高缓存。程序的指令和数据分开有利于提高程序的局部性。现代的cpu缓存都设计成指令缓存和数据缓存。</span></p><p style="margin-left:63.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">3.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">第三个原因就是当系统中运行该程序的多个副本时，指令都是一样的，所以内存中只需要保存一份程序指令部分集合。对于指令这种只读区域来说是这样的，对于其他的只读数据也是这样。当然每个进程的数据区域不一样，他们是进程私有的。</span></p><img src ="http://www.cppblog.com/MyCBlog/aggbug/164966.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-05 03:49 <a href="http://www.cppblog.com/MyCBlog/articles/164966.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Gcc和G++区别</title><link>http://www.cppblog.com/MyCBlog/articles/164965.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Sat, 04 Feb 2012 18:21:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/164965.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/164965.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/164965.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/164965.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/164965.html</trackback:ping><description><![CDATA[<div style="font-family: 宋体; text-align: -webkit-left; ">&nbsp;&nbsp; 我们在编译c/c++代码的时候，有人用gcc，有人用g++，于是各种说法都来了，譬如c代码用gcc，而c++代码用g++，或者说编译用gcc，链接用g++，一时也不知哪个说法正确，如果再遇上个extern "C"，分歧就更多了，这里我想作个了结，毕竟知识的目的是令人更清醒，而不是更糊涂。</div><div style="font-family: 宋体; text-align: -webkit-left; ">&nbsp;</div><div style="font-family: 宋体; text-align: -webkit-left; "><strong>误区一:gcc只能编译c代码,g++只能编译c++代码</strong><br />两者都可以，但是请注意：</div><div style="font-family: 宋体; text-align: -webkit-left; ">1.后缀为.c的，gcc把它当作是C程序，而g++当作是c++程序；后缀为.cpp的，两者都会认为是c++程序，注意，虽然c++是c的超集，但是两者对语法的要求是有区别的，例如：</div><div style="font-family: 宋体; text-align: -webkit-left; ">#include &lt;stdio.h&gt;</div><div style="font-family: 宋体; text-align: -webkit-left; ">int main(int argc, char* argv[]) {<br />&nbsp;&nbsp; if(argv == 0) return;</div><div style="font-family: 宋体; text-align: -webkit-left; ">&nbsp;&nbsp; printString(argv);</div><div style="font-family: 宋体; text-align: -webkit-left; ">&nbsp;&nbsp;&nbsp;return;<br />}<br />int printString(char* string) {<br />&nbsp; sprintf(string, "This is a test.\n");<br />}</div><div style="font-family: 宋体; text-align: -webkit-left; ">如果按照C的语法规则，OK，没问题，但是，一旦把后缀改为cpp，立刻报三个错：&#8220;printString未定义&#8221;；</div><div style="font-family: 宋体; text-align: -webkit-left; ">&#8220;cannot convert `char**' to `char*&#8221;；</div><div style="font-family: 宋体; text-align: -webkit-left; ">&#8221;return-statement with no value&#8220;；</div><div style="font-family: 宋体; text-align: -webkit-left; ">分别对应前面红色标注的部分。可见C++的语法规则更加严谨一些。</div><div style="font-family: 宋体; text-align: -webkit-left; ">2.编译阶段，g++会调用gcc，对于c++代码，两者是等价的，但是因为gcc命令不能自动和C＋＋程序使用的库联接，所以通常用g++来完成链接，为了统一起见，干脆编译/链接统统用g++了，这就给人一种错觉，好像cpp程序只能用g++似的。</div><div style="font-family: 宋体; text-align: -webkit-left; ">&nbsp;</div><div style="font-family: 宋体; text-align: -webkit-left; "><strong>误区二:gcc不会定义__cplusplus宏，而g++会</strong><br />实际上，这个宏只是标志着编译器将会把代码按C还是C++语法来解释，如上所述，如果后缀为.c，并且采用gcc编译器，则该宏就是未定义的，否则，就是已定义。</div><div style="font-family: 宋体; text-align: -webkit-left; ">&nbsp;</div><div style="font-family: 宋体; text-align: -webkit-left; "><strong>误区三:编译只能用gcc，链接只能用g++<br /></strong>严格来说，这句话不算错误，但是它混淆了概念，应该这样说：编译可以用gcc/g++，而链接可以用g++或者gcc -lstdc++。因为gcc命令不能自动和C＋＋程序使用的库联接，所以通常使用g++来完成联接。但在编译阶段，g++会自动调用gcc，二者等价。</div><div style="font-family: 宋体; text-align: -webkit-left; ">&nbsp;</div><div style="font-family: 宋体; text-align: -webkit-left; "><strong>误区四:extern "C"与gcc/g++有关系</strong><br />实际上并无关系，无论是gcc还是g++，用extern "c"时，都是以C的命名方式来为symbol命名，否则，都以c++方式命名。试验如下：<br /><em>me.h</em>：<br />extern "C" void CppPrintf(void);</div><div style="font-family: 宋体; text-align: -webkit-left; ">&nbsp;</div><div style="font-family: 宋体; text-align: -webkit-left; "><em>me.cpp</em>:<br />#include &lt;iostream&gt;<br />#include "me.h"<br />using namespace std;<br />void CppPrintf(void)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Hello\n";<br />}</div><div style="font-family: 宋体; text-align: -webkit-left; ">&nbsp;</div><div style="font-family: 宋体; text-align: -webkit-left; "><em>test.cpp:</em><br />#include &lt;stdlib.h&gt;<br />#include &lt;stdio.h&gt;<br />#include "me.h"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />int main(void)<br />{<br />&nbsp;&nbsp;&nbsp; CppPrintf();<br />&nbsp;&nbsp;&nbsp; return 0;<br />}</div><div style="font-family: 宋体; text-align: -webkit-left; ">&nbsp;</div><div style="font-family: 宋体; text-align: -webkit-left; "><strong>1. 先给me.h加上extern "C"，看用gcc和g++命名有什么不同</strong><br />[root@root G++]# g++ -S me.cpp<br />[root@root G++]# less me.s<br />.globl _Z9CppPrintfv&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注意此函数的命名<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .type&nbsp;&nbsp; CppPrintf, @function</div><div style="font-family: 宋体; text-align: -webkit-left; ">[root@root GCC]# gcc -S me.cpp<br />[root@root GCC]# less me.s<br />.globl _Z9CppPrintfv&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注意此函数的命名<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .type&nbsp;&nbsp; CppPrintf, @function<br />完全相同！<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><strong>2. 去掉me.h中extern "C"，看用gcc和g++命名有什么不同<br /></strong>[root@root GCC]# gcc -S me.cpp<br />[root@root GCC]# less me.s<br />.globl _Z9CppPrintfv&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注意此函数的命名<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .type&nbsp;&nbsp; _Z9CppPrintfv, @function</div><div style="font-family: 宋体; text-align: -webkit-left; ">[root@root G++]# g++ -S me.cpp<br />[root@root G++]# less me.s<br />.globl _Z9CppPrintfv&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注意此函数的命名<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .type&nbsp;&nbsp; _Z9CppPrintfv, @function<br />完全相同！</div><div style="font-family: 宋体; text-align: -webkit-left; "><strong>【结论】</strong>完全相同，可见extern "C"与采用gcc/g++并无关系，以上的试验还间接的印证了前面的说法：在编译阶段，g++是调用gcc的。</div><img src ="http://www.cppblog.com/MyCBlog/aggbug/164965.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-05 02:21 <a href="http://www.cppblog.com/MyCBlog/articles/164965.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>符号决议</title><link>http://www.cppblog.com/MyCBlog/articles/164963.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Sat, 04 Feb 2012 17:21:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/164963.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/164963.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/164963.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/164963.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/164963.html</trackback:ping><description><![CDATA[<p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">每个源代码模块独立编译，然后按照需要将他们组装起来，这个组装模块的过程，就是链接。链接的主要内容，就是把各个模块之间相互引用的部分都处理好，使得各个模块之间能够正确地衔接。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">链接的过程，主要包括了</span><span style=" font-weight:bold; font-size:10.5000pt; font-family:'宋体'; ">地址和空间分配，负号决议，重定位</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">等步骤。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">符号决议有时候也被叫做符号绑定，名称决议；决议更倾向于静态链接，而绑定更倾向于动态链接。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">源文件经过编译器编译成目标文件，目标文件和库文件一起链接形成最终可执行文件。而最常用的库就是运行时库，他是支持程序运行的基本函数的集合。库其实是一组目标文件的包，就是一些最常用的编码已编译目标文件打包存放。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">很多时候，我们把目标文件称作为模块。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">现代的编译和链接过程也并非想象的那么复杂。比如我们在程序模块main.c中使用两外一个func.c中函数方法foo（）。我们在main.c的模块中每一处调用foo的时候都必须确切知道foo这个函数的地址，但是每个模块都是单独编译的，在编译器编译main.c的时候，并不知道foo函数的地址，所以他暂时把这些调用foo的指令的目标地址搁置，等待最后连接的时候有编译器将这些指令的目标地址修订。使用连接器，你可以直接饮用其他模块的函数和全局变量而无需知道他们的地址，因为连接器在连接的时候，会根据你所饮用的foo，自动去响应的func.c模块查找foo的地址，然后将main.c模块中所引用的符号foo，自动去响应的func.c模块查找foo的地址，然后将main。C模块汇总所引用的foo的指令重新修正，让他们去响应的func.c模块查找foo的地址，然后将main.c模块中缩影的foo指令重新修正，让他们的目标地址为真正的foo函数的地址。这就是静态链接的最基本过程和作用。</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">在链接的过程中，对其他定义在目标文件中的函数调用的指令需要被诚信调整，对使用其他定义在其他目标文件的变量来说，也存在同样的问题，让我们结合具体的cpu指令来了解这个过程。假设我们有个全局变量var，他在目标文件A里面。我们在目标文件B里面要访问这个全局变量，比如我们在目标文件B里面有这么一条指令：</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">Movl&nbsp;&nbsp;&nbsp;&nbsp;s0x2a&nbsp;，&nbsp;&nbsp;&nbsp;var</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">这条指令就是给这个var变量赋值，相当于c语言中的语句var&nbsp;=&nbsp;42；然后我们编译目标文件B，得到这条机器码，如图：</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">Mov指令码&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;源常量</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style="position:absolute; z-index:1; left:0px; margin-left:30.9333px; margin-top:2.2000px; width:255.0000px; height:35.0000px; "><img width="255" height="35" src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps_clip_image-23879.png" alt="" /></span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">士大夫</span></p><p style="text-indent:21.0000pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">由于编译目标文件B的时候，编译器并不知道变量var的目标地址，所以编译器在没有确定地址的情况下，将这条指令的目标地址置为0，等待连接器在将目标文件A和B连接起来的时候在将其修正。我们假设A和B连接后，变量var的地址确定下来为0x1000，那么连接器将会把这个指令的目标地址部分修正为0x1000，这个地址修订的过程，叫做</span><span style=" font-weight:bold; font-size:10.5000pt; font-family:'宋体'; ">重定位</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">。每个要修正的地方叫做</span><span style=" font-weight:bold; font-size:10.5000pt; font-family:'宋体'; ">重定位入口</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">。</span></p><img src ="http://www.cppblog.com/MyCBlog/aggbug/164963.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-05 01:21 <a href="http://www.cppblog.com/MyCBlog/articles/164963.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用def文件导出函数</title><link>http://www.cppblog.com/MyCBlog/articles/164916.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Fri, 03 Feb 2012 15:31:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/164916.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/164916.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/164916.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/164916.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/164916.html</trackback:ping><description><![CDATA[<div><span style="font-family: Arial; line-height: normal; background-color: #ffffff; ">DLL</span>中导出函数的声明有两种方式：一种为在函数声明中加上__declspec(dllexport)，这里不再举例说明；另外一种方式是采用模块定义(.def)&nbsp;文件声明，.def文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。&nbsp;<br /><div><p style="margin-bottom:0pt; margin-top:0pt; "><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">首先创建&nbsp;一个DLL程序，.cpp中<br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">int</span>&nbsp;__stdcall&nbsp;Add(<span style="color: #0000FF; ">int</span>&nbsp;numa,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;numb)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;(numa&nbsp;+&nbsp;numb);<br />}<br /><span style="color: #0000FF; ">int</span>&nbsp;__stdcall&nbsp;Sub(<span style="color: #0000FF; ">int</span>&nbsp;numa,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;numb)<br />{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; &nbsp;<span style="color: #0000FF; ">return</span>&nbsp;(numa&nbsp;-&nbsp;numb);<br />}</div><div><p style="margin-bottom: 0pt; margin-top: 0pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-size: 10.5pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">然后创建一个.def的文件，在里面加上</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style="font-size: 10.5pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;DllTestDef.lib&nbsp;:&nbsp;导出DLL函数</span><span style="font-size: 10.5pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><br /></span><span style="font-size: 10.5pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;作者：----</span><span style="font-size: 10.5pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><br /></span><span style="font-size: 10.5pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LIBRARY&nbsp;DllTestDef</span><span style="font-size: 10.5pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><br /></span><span style="font-size: 10.5pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EXPORTS&nbsp;</span><span style="font-size: 10.5pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><br /></span><span style="font-size: 10.5pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Add&nbsp;@&nbsp;1</span><span style="font-size: 10.5pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><br /></span><span style="font-size: 10.5pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sub&nbsp;@&nbsp;2<br />最后创建测试程序：<br /></span></p><div style="font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-image: initial; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; background-color: #eeeeee; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include&nbsp;&lt;iostream&gt;<br />#include&nbsp;&lt;windows.h&gt;<br /><span style="color: #0000FF; ">using</span>&nbsp;<span style="color: #0000FF; ">namespace</span>&nbsp;std;<br />typedef&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;(__stdcall&nbsp;*FUN)(<span style="color: #0000FF; ">int</span>,&nbsp;<span style="color: #0000FF; ">int</span>);HINSTANCE&nbsp;hInstance;<br />FUN&nbsp;&nbsp;&nbsp;fun;<br /><span style="color: #0000FF; ">int</span>&nbsp;main()<br />{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hInstance&nbsp;=&nbsp;LoadLibrary("DLLTestDef.dll");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(!hInstance)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;&lt;&lt;&nbsp;"Not&nbsp;Find&nbsp;this&nbsp;Dll"&nbsp;&lt;&lt;&nbsp;endl;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; fun&nbsp;=&nbsp;(FUN)GetProcAddress(hInstance,&nbsp;MAKEINTRESOURCE(1));&nbsp;&nbsp;<br />&nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(!fun)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;<br />&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;&lt;&lt;&nbsp;"not&nbsp;find&nbsp;this&nbsp;fun"&nbsp;&lt;&lt;&nbsp;endl;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;&lt;&lt;&nbsp;fun(1,&nbsp;2)&nbsp;&lt;&lt;&nbsp;endl;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FreeLibrary(hInstance);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;<br />}</div><div><p style="margin-bottom:0pt; margin-top:0pt; "><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">说明：</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; "><br /></span><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">.def文件的规则为：</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; "><br /></span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; "><br /></span><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">　　(1)LIBRARY语句说明.def文件相应的DLL；</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; "><br /></span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; "><br /></span><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">　　(2)EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n，表示要导出函数的序号为n（在进行函数调用时，这个序号将发挥其作用）；</span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; "><br /></span><span style="mso-spacerun:'yes'; font-size:10.5000pt; font-family:'Times New Roman'; "><br /></span><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">　　(3).def&nbsp;文件中的注释由每个注释行开始处的分号&nbsp;(;)&nbsp;指定，且注释不能与语句共享一行。</span>&nbsp;</p></div><p>&nbsp;</p></div><p>&nbsp;</p></div></div><img src ="http://www.cppblog.com/MyCBlog/aggbug/164916.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-03 23:31 <a href="http://www.cppblog.com/MyCBlog/articles/164916.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编译调用约定</title><link>http://www.cppblog.com/MyCBlog/articles/164914.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Fri, 03 Feb 2012 14:58:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/164914.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/164914.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/164914.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/164914.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/164914.html</trackback:ping><description><![CDATA[<div><p style="margin-bottom: 7.5pt; margin-top: 0pt; border-bottom-width: 0.75pt; border-bottom-style: solid; border-bottom-color: #dedfe1; padding-top: 0pt; padding-right: 0pt; padding-bottom: 6pt; padding-left: 0pt; line-height: 18pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-weight: bold; font-size: 13.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">几种函数调用方式</span></p><p style="margin-left: 21.25pt; text-indent: -21.25pt; margin-bottom: 7.5pt; margin-top: 0pt; border-bottom-width: 0.75pt; border-bottom-style: solid; border-bottom-color: #dedfe1; padding-top: 0pt; padding-right: 0pt; padding-bottom: 6pt; padding-left: 0pt; line-height: 18pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">1.&nbsp;</span><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">_stdcall&nbsp;是StandardCall的缩写，是C++的标准调用方式：所有参数从右到左依次入栈，如果是调用类成员的话，最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回后清除，使用的指令是&nbsp;retnX，X表示参数占用的字节数，CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。函数在编译的时候就必须确定参数个数，并且调用者必须严格的控制参数的生成，不能多，不能少，否则返回后会出错。　　PASCAL&nbsp;是</span><a href="http://baike.baidu.com/view/765708.htm"><span style="color: #136ec2; font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">Pascal语言</span></a><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">的函数调用方式，也可以在C/C++中使用，参数压栈顺序与前两者相反。返回时的清栈方式与_stdcall相同。　</span></p><p style="margin-left: 21.25pt; text-indent: -21.25pt; margin-bottom: 7.5pt; margin-top: 0pt; border-bottom-width: 0.75pt; border-bottom-style: solid; border-bottom-color: #dedfe1; padding-top: 0pt; padding-right: 0pt; padding-bottom: 6pt; padding-left: 0pt; line-height: 18pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">2.&nbsp;</span><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">_cdecl&nbsp;是C&nbsp;DECLaration的缩写（declaration，声明），表示C语言默认的函数调用方法：所有参数从右到左依次入栈，这些参数由调用者清除，称为手动清栈。被调用函数不会要求调用者传递多少参数，调用者传递过多或者过少的参数，甚至完全不同的参数都不会产生编译阶段的错误。</span>&nbsp;</p><p style="margin-left: 21.25pt; text-indent: -21.25pt; margin-bottom: 7.5pt; margin-top: 0pt; border-bottom-width: 0.75pt; border-bottom-style: solid; border-bottom-color: #dedfe1; padding-top: 0pt; padding-right: 0pt; padding-bottom: 6pt; padding-left: 0pt; line-height: 18pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">3.&nbsp;</span><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">_fastcall是</span><a href="http://baike.baidu.com/view/487018.htm"><span style="color: #136ec2; font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">编译器</span></a><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">指定的快速调用方式。由于大多数的函数参数个数很少，使用堆栈传递比较费时。因此_fastcall通常规定将前两个（或若干个）参数由寄存器传递，其余参数还是通过堆栈传递。不同编译器编译的程序规定的寄存器不同。返回方式和_stdcall相当。　　</span></p><p style="margin-left: 21.25pt; text-indent: -21.25pt; margin-bottom: 7.5pt; margin-top: 0pt; border-bottom-width: 0.75pt; border-bottom-style: solid; border-bottom-color: #dedfe1; padding-top: 0pt; padding-right: 0pt; padding-bottom: 6pt; padding-left: 0pt; line-height: 18pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">4.&nbsp;</span><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">_thiscall&nbsp;是为了解决类成员调用中this指针传递而规定的。_thiscall要求把this指针放在特定寄存器中，该寄存器由编译器决定。VC使用ecx，Borland的C++编译器使用eax。返回方式和_stdcall相当。　　_fastcall&nbsp;和&nbsp;_thiscall涉及的寄存器由编译器决定，因此不能用作跨编译器的接口。所以Windows上的COM对象接口都定义为_stdcall调用方式。　　C中不加说明默认函数为_cdecl方式（C中也只能用这种方式），C++也一样，但是默认的调用方式可以在IDE环境中设置。　　带有可变参数的函数必须且只能使用_cdecl方式，例如下面的函数:　　int&nbsp;printf(char&nbsp;*&nbsp;fmtStr,&nbsp;...);　　int&nbsp;scanf(char&nbsp;*&nbsp;fmtStr,&nbsp;...);　</span></p><p style="margin-bottom: 7.5pt; margin-top: 0pt; border-bottom-width: 0.75pt; border-bottom-style: solid; border-bottom-color: #dedfe1; padding-top: 0pt; padding-right: 0pt; padding-bottom: 6pt; padding-left: 0pt; line-height: 18pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-weight: bold; font-size: 13.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">几种调用约定的区别</span></p><p style="text-indent: 21pt; margin-bottom: 7.5pt; margin-top: 0pt; border-bottom-width: 0.75pt; border-bottom-style: solid; border-bottom-color: #dedfe1; padding-top: 0pt; padding-right: 0pt; padding-bottom: 6pt; padding-left: 0pt; line-height: 18pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">__cdecl&nbsp;__fastcall与&nbsp;</span><a href="http://baike.baidu.com/view/1276580.htm"><span style="color: #136ec2; font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">__stdcall</span></a><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">，三者都是调用约定(Calling&nbsp;convention)，它决定以下内容：</span></p><p style="text-indent: 21pt; margin-bottom: 7.5pt; margin-top: 0pt; border-bottom-width: 0.75pt; border-bottom-style: solid; border-bottom-color: #dedfe1; padding-top: 0pt; padding-right: 0pt; padding-bottom: 6pt; padding-left: 0pt; line-height: 18pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">1)</span><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">函数参数的压栈顺序，</span></p><p style="text-indent: 21pt; margin-bottom: 7.5pt; margin-top: 0pt; border-bottom-width: 0.75pt; border-bottom-style: solid; border-bottom-color: #dedfe1; padding-top: 0pt; padding-right: 0pt; padding-bottom: 6pt; padding-left: 0pt; line-height: 18pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">2)</span><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">由调用者还是被调用者把参数弹出栈，</span></p><p style="text-indent: 21pt; margin-bottom: 7.5pt; margin-top: 0pt; border-bottom-width: 0.75pt; border-bottom-style: solid; border-bottom-color: #dedfe1; padding-top: 0pt; padding-right: 0pt; padding-bottom: 6pt; padding-left: 0pt; line-height: 18pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">3)</span><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">以及产生函数修饰名的方法。　</span></p><p style="margin-bottom: 7.5pt; margin-top: 0pt; border-bottom-width: 0.75pt; border-bottom-style: solid; border-bottom-color: #dedfe1; padding-top: 0pt; padding-right: 0pt; padding-bottom: 6pt; padding-left: 0pt; line-height: 18pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-weight: bold; font-size: 13.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">修饰约定</span></p><p style="margin-left: 21.25pt; text-indent: -21.25pt; margin-bottom: 7.5pt; margin-top: 0pt; border-bottom-width: 0.75pt; border-bottom-style: solid; border-bottom-color: #dedfe1; padding-top: 0pt; padding-right: 0pt; padding-bottom: 6pt; padding-left: 0pt; line-height: 18pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">1.&nbsp;</span><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">　__stdcall调用约定在输出函数名前加上一个下划线前缀，后面加上一个"@"符号和其参数的字节数，格式为_functionname@number,例如&nbsp;：function(int&nbsp;a,&nbsp;int&nbsp;b)，其修饰名为：_function@8　　</span></p><p style="margin-left: 21.25pt; text-indent: -21.25pt; margin-bottom: 7.5pt; margin-top: 0pt; border-bottom-width: 0.75pt; border-bottom-style: solid; border-bottom-color: #dedfe1; padding-top: 0pt; padding-right: 0pt; padding-bottom: 6pt; padding-left: 0pt; line-height: 18pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">2.&nbsp;</span><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">__cdecl调用约定仅在输出函数名前加上一个下划线前缀，格式为_functionname</span></p><p style="margin-left: 21.25pt; text-indent: -21.25pt; margin-bottom: 7.5pt; margin-top: 0pt; border-bottom-width: 0.75pt; border-bottom-style: solid; border-bottom-color: #dedfe1; padding-top: 0pt; padding-right: 0pt; padding-bottom: 6pt; padding-left: 0pt; line-height: 18pt; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; "><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">3.&nbsp;</span><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">__fastcall调用约定在输出函数名前加上一个"@"符号，后面也是一个"@"符号和其参数的字节数，格式为@functionname@number</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style="font-size: 10.5pt; font-family: Arial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-position: initial initial; background-repeat: initial initial; ">　　</span></p></div><img src ="http://www.cppblog.com/MyCBlog/aggbug/164914.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-03 22:58 <a href="http://www.cppblog.com/MyCBlog/articles/164914.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DLL的加载与卸载</title><link>http://www.cppblog.com/MyCBlog/articles/164912.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Fri, 03 Feb 2012 14:09:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/164912.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/164912.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/164912.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/164912.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/164912.html</trackback:ping><description><![CDATA[<div><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">DLL内的函数分为两种：</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">(1)DLL导出函数，可供应用程序调用；</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">(2)&nbsp;DLL内部函数，只能在DLL程序使用，应用程序无法调用它们。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">而应用程序对本DLL的调用和对第2节静态链接库的调用却有较大差异，下面我们来逐一分析。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">首先，语句typedef&nbsp;int&nbsp;(&nbsp;*&nbsp;lpAddFun)(int,int)定义了一个与add函数接受参数类型和返回值均相同的函数指针类型。随后，在main函数中定义了lpAddFun的实例addFun；</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">其次，在函数main中定义了一个DLL&nbsp;HINSTANCE句柄实例hDll，通过Win32&nbsp;Api函数LoadLibrary动态加载了DLL模块并将DLL模块句柄赋给了hDll；</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">再次，在函数main中通过Win32&nbsp;Api函数GetProcAddress得到了所加载DLL模块中函数add的地址并赋给了addFun。经由函数指针addFun进行了对DLL中add函数的调用；</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">最后，应用工程使用完DLL后，在函数main中通过Win32&nbsp;Api函数FreeLibrary释放了已经加载的DLL模块。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">通过这个简单的例子，我们获知DLL定义和调用的一般概念：</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">(1)DLL中需以某种特定的方式声明导出函数（或变量、类）；</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">(2)应用工程需以某种特定的方式调用DLL的导出函数（或变量、类）。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">下面我们来对&#8220;特定的方式进行&#8221;阐述。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">（1）&nbsp;声明导出函数</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">DLL中导出函数的声明有两种方式：一种为4.1节例子中给出的在函数声明中加上__declspec(dllexport)，这里不再举例说明；另外一种方式是采用模块定义(.def)&nbsp;文件声明，.def文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">下面的代码演示了怎样同.def文件将函数add声明为DLL导出函数（需在dllTest工程中添加lib.def文件）：</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">;&nbsp;lib.def&nbsp;:&nbsp;导出DLL函数</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">LIBRARY&nbsp;dllTest</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">EXPORTS</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">add&nbsp;@&nbsp;1</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">.def文件的规则为：</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">(1)LIBRARY语句说明.def文件相应的DLL；</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">(2)EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n，表示要导出函数的序号为n（在进行函数调用时，这个序号将发挥其作用）；</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">(3).def&nbsp;文件中的注释由每个注释行开始处的分号&nbsp;(;)&nbsp;指定，且注释不能与语句共享一行。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">由此可以看出，例子中lib.def文件的含义为生成名为&#8220;dllTest&#8221;的动态链接库，导出其中的add函数，并指定add函数的序号为1。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">（2）&nbsp;DLL的调用方式</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">在4.1节的例子中我们看到了由&#8220;LoadLibrary-GetProcAddress-FreeLibrary&#8221;系统Api提供的三位一体&#8220;DLL加载-DLL函数地址获取-DLL释放&#8221;方式，这种调用方式称为DLL的动态调用。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">动态调用方式的特点是完全由编程者用&nbsp;API&nbsp;函数加载和卸载&nbsp;DLL，程序员可以决定&nbsp;DLL&nbsp;文件何时加载或不加载，显式链接在运行时决定加载哪个&nbsp;DLL&nbsp;文件。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">静态调用方式的特点是由编译系统完成对DLL的加载和应用程序结束时&nbsp;DLL&nbsp;的卸载。当调用某DLL的应用程序结束时，若系统中还有其它程序使用该&nbsp;DLL，则Windows对DLL的应用记录减1，直到所有使用该DLL的程序都结束时才释放它。静态调用方式简单实用，但不如动态调用方式灵活。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">下面我们来看看静态调用的例子（单击此处下载本工程附件），将编译dllTest工程所生成的.lib和.dll文件拷入dllCall工程所在的路径，dllCall执行下列代码：</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">#pragma&nbsp;comment(lib,"dllTest.lib")</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">//.lib文件中仅仅是关于其对应DLL文件中函数的重定位信息</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">extern&nbsp;"C"&nbsp;__declspec(dllimport)&nbsp;add(int&nbsp;x,int&nbsp;y);</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">int&nbsp;main(int&nbsp;argc,&nbsp;char*&nbsp;argv[])</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">{</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">int&nbsp;result&nbsp;=&nbsp;add(2,3);</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">printf("%d",result);</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">return&nbsp;0;</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">}</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">由上述代码可以看出，静态调用方式的顺利进行需要完成两个动作：</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">(1)告诉编译器与DLL相对应的.lib文件所在的路径及文件名，#pragma&nbsp;comment(lib,"dllTest.lib")就是起这个作用。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">程序员在建立一个DLL文件时，连接器会自动为其生成一个对应的.lib文件，该文件包含了DLL&nbsp;导出函数的符号名及序号（并不含有实际的代码）。在应用程序里，.lib文件将作为DLL的替代文件参与编译。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">(2)声明导入函数，extern&nbsp;"C"&nbsp;__declspec(dllimport)&nbsp;add(int&nbsp;x,int&nbsp;y)语句中的__declspec(dllimport)发挥这个作用。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">静态调用方式不再需要使用系统API来加载、卸载DLL以及获取DLL中导出函数的地址。这是因为，当程序员通过静态链接方式编译生成应用程序时，应用程序中调用的与.lib文件中导出符号相匹配的函数符号将进入到生成的EXE&nbsp;文件中，.lib文件中所包含的与之对应的DLL文件的文件名也被编译器存储在&nbsp;EXE文件内部。当应用程序运行过程中需要加载DLL文件时，Windows将根据这些信息发现并加载DLL，然后通过符号名实现对DLL&nbsp;函数的动态链接。这样，EXE将能直接通过函数名调用DLL的输出函数，就象调用程序内部的其他函数一样。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">DllMain函数</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">Windows在加载DLL的时候，需要一个入口函数，就如同控制台或DOS程序需要main函数、WIN32程序需要WinMain函数一样。在前面的例子中，DLL并没有提供DllMain函数，应用工程也能成功引用DLL，这是因为Windows在找不到DllMain的时候，系统会从其它运行库中引入一个不做任何操作的缺省DllMain函数版本，并不意味着DLL可以放弃DllMain函数。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">根据编写规范，Windows必须查找并执行DLL里的DllMain函数作为加载DLL的依据，它使得DLL得以保留在内存里。这个函数并不属于导出函数，而是DLL的内部函数。这意味着不能直接在应用工程中引用DllMain函数，DllMain是自动被调用的。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">我们来看一个DllMain函数的例子（单击此处下载本工程附件）。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">BOOL&nbsp;APIENTRY&nbsp;DllMain(&nbsp;HANDLE&nbsp;hModule,</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">DWORD&nbsp;ul_reason_for_call,</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">LPVOID&nbsp;lpReserved</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">)</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">{</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">switch&nbsp;(ul_reason_for_call)</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">{</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">case&nbsp;DLL_PROCESS_ATTACH:</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">printf("/nprocess&nbsp;attach&nbsp;of&nbsp;dll");</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">break;</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">case&nbsp;DLL_THREAD_ATTACH:</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">printf("/nthread&nbsp;attach&nbsp;of&nbsp;dll");</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">break;</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">case&nbsp;DLL_THREAD_DETACH:</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">printf("/nthread&nbsp;detach&nbsp;of&nbsp;dll");</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">break;</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">case&nbsp;DLL_PROCESS_DETACH:</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">printf("/nprocess&nbsp;detach&nbsp;of&nbsp;dll");</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">break;</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">}</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">return&nbsp;TRUE;</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">}</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">DllMain函数在DLL被加载和卸载时被调用，在单个线程启动和终止时，DLLMain函数也被调用，ul_reason_for_call指明了被调用的原因。原因共有4种，即PROCESS_ATTACH、PROCESS_DETACH、THREAD_ATTACH和THREAD_DETACH，以switch语句列出。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">来仔细解读一下DllMain的函数头BOOL&nbsp;APIENTRY&nbsp;DllMain(&nbsp;HANDLE&nbsp;hModule,&nbsp;WORD&nbsp;ul_reason_for_call,&nbsp;LPVOID&nbsp;lpReserved&nbsp;)。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">APIENTRY被定义为__stdcall，它意味着这个函数以标准Pascal的方式进行调用，也就是WINAPI方式；</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">进程中的每个DLL模块被全局唯一的32字节的HINSTANCE句柄标识，只有在特定的进程内部有效，句柄代表了DLL模块在进程虚拟空间中的起始地址。在Win32中，HINSTANCE和HMODULE的值是相同的，这两种类型可以替换使用，这就是函数参数hModule的来历。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">执行下列代码：</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">hDll&nbsp;=&nbsp;LoadLibrary("..//Debug//dllTest.dll");</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">if&nbsp;(hDll&nbsp;!=&nbsp;NULL)</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">{</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">addFun&nbsp;=&nbsp;(lpAddFun)GetProcAddress(hDll,&nbsp;MAKEINTRESOURCE(1));</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">//MAKEINTRESOURCE直接使用导出文件中的序号</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">if&nbsp;(addFun&nbsp;!=&nbsp;NULL)</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">{</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">int&nbsp;result&nbsp;=&nbsp;addFun(2,&nbsp;3);</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">printf("/ncall&nbsp;add&nbsp;in&nbsp;dll:%d",&nbsp;result);</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">}</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">FreeLibrary(hDll);</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">}</span></p><p style="margin-bottom:0pt; margin-top:0pt; "></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">我们看到输出顺序为：</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">process&nbsp;attach&nbsp;of&nbsp;dll</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">call&nbsp;add&nbsp;in&nbsp;dll:5</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">process&nbsp;detach&nbsp;of&nbsp;dll</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">这一输出顺序验证了DllMain被调用的时机。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">代码中的GetProcAddress&nbsp;(&nbsp;hDll,&nbsp;MAKEINTRESOURCE&nbsp;(&nbsp;1&nbsp;)&nbsp;)值得留意，它直接通过.def文件中为add函数指定的顺序号访问add函数，具体体现在MAKEINTRESOURCE&nbsp;(&nbsp;1&nbsp;)，MAKEINTRESOURCE是一个通过序号获取函数名的宏，定义为（节选自winuser.h）：</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">#define&nbsp;MAKEINTRESOURCEA(i)&nbsp;(LPSTR)((DWORD)((WORD)(i)))</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">#define&nbsp;MAKEINTRESOURCEW(i)&nbsp;(LPWSTR)((DWORD)((WORD)(i)))</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">#ifdef&nbsp;UNICODE</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">#define&nbsp;MAKEINTRESOURCE&nbsp;MAKEINTRESOURCEW</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">#else</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">#define&nbsp;MAKEINTRESOURCE&nbsp;MAKEINTRESOURCEA</span></p></div><img src ="http://www.cppblog.com/MyCBlog/aggbug/164912.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-03 22:09 <a href="http://www.cppblog.com/MyCBlog/articles/164912.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vs2010环境下生成dll文件 </title><link>http://www.cppblog.com/MyCBlog/articles/164910.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Fri, 03 Feb 2012 13:21:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/164910.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/164910.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/164910.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/164910.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/164910.html</trackback:ping><description><![CDATA[1，新建win32工程，选中DLL项目，如下图：<br /><img src="http://www.cppblog.com/images/cppblog_com/mycblog/vs2010环境下生成dll文件1.jpg" width="622" height="522" alt="" /><br />2，分别添加头文件和cpp文件<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#ifndef&nbsp;LIB_H<br /><span style="color: #0000FF; ">#define</span>&nbsp;LIB_H<br /><span style="color: #0000FF; ">extern</span>&nbsp;"C"&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;_declspec(dllexport)add(<span style="color: #0000FF; ">int</span>&nbsp;x,<span style="color: #0000FF; ">int</span>&nbsp;y);&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;声明为C编译、链接方式的外部函数</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">#endif</span></div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include&nbsp;"stdafx.h"<br /><span style="color: #0000FF; ">int</span>&nbsp;add(<span style="color: #0000FF; ">int</span>&nbsp;x,<span style="color: #0000FF; ">int</span>&nbsp;y)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;x+y;<br />}</div>3，新建win32控制台工程，添加头文件后，然后在main函数中写下如下的代码：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include&nbsp;"stdafx.h"<br /><span style="color: #0000FF; ">using</span>&nbsp;<span style="color: #0000FF; ">namespace</span>&nbsp;std;<br /><span style="color: #0000FF; ">int</span>&nbsp;_tmain(<span style="color: #0000FF; ">int</span>&nbsp;argc,&nbsp;_TCHAR*&nbsp;argv[])<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;<span style="color: #0000FF; ">int</span>(*lpAddFun)(<span style="color: #0000FF; ">int</span>,<span style="color: #0000FF; ">int</span>);<span style="color: #008000; ">//</span><span style="color: #008000; ">宏定义函数指针类型</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;HINSTANCE&nbsp;&nbsp;hInst=NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;lpAddFun&nbsp;addFun;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">函数指针</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;hInst=::LoadLibraryA("C:\\Users\\Administrator\\Documents\\Visual&nbsp;Studio&nbsp;2010\\Projects\\Win32Study\\Debug\\test_1.dll");<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(hInst==NULL)&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Load&nbsp;mydll.DLL&nbsp;fail!\n");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addFun=(lpAddFun)GetProcAddress(hInst,"add");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(addFun!=NULL)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;result=addFun(2,3);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;result&lt;&lt;endl;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getchar();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;FreeLibrary(hInst);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;<br />}</div>4，运行结果如下图：<br /><img src="http://www.cppblog.com/images/cppblog_com/mycblog/vs2010环境下生成dll文件2.jpg" width="676" height="440" alt="" /><img src ="http://www.cppblog.com/MyCBlog/aggbug/164910.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-03 21:21 <a href="http://www.cppblog.com/MyCBlog/articles/164910.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vs2010环境下生成lib文件</title><link>http://www.cppblog.com/MyCBlog/articles/164901.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Fri, 03 Feb 2012 09:46:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/164901.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/164901.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/164901.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/164901.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/164901.html</trackback:ping><description><![CDATA[1，新建win32工程，选中lib项目：如图：<br /><img src="http://www.cppblog.com/images/cppblog_com/mycblog/vs2010环境下生成lib文件1.png" width="627" height="530" alt="" /><br />2，然后在工程项目中lib.h添加如下代码：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#ifndef&nbsp;LIB_H<br /><span style="color: #0000FF; ">#define</span>&nbsp;LIB_H<br /><span style="color: #0000FF; ">extern</span>&nbsp;"C"&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;add(<span style="color: #0000FF; ">int</span>&nbsp;x,<span style="color: #0000FF; ">int</span>&nbsp;y);&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;声明为C编译、链接方式的外部函数</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">#endif</span></div>3，在项目中添加lib.cpp文件，代码如下：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include&nbsp;"lib.h"<br /><span style="color: #0000FF; ">int</span>&nbsp;add(<span style="color: #0000FF; ">int</span>&nbsp;x,<span style="color: #0000FF; ">int</span>&nbsp;y)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;x+y;<br />}</div>4，然后生成以下就行了。<br />5，新建空项目，添加lib.h文件，在主文件中，添加如下代码：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include&nbsp;&lt;iostream&gt;<br />#include&nbsp;"lib.h"<br /><span style="color: #0000FF; ">using</span>&nbsp;<span style="color: #0000FF; ">namespace</span>&nbsp;std;<br /><span style="color: #0000FF; ">int</span>&nbsp;main()<br />{<br />&nbsp;&nbsp;&nbsp;cout&lt;&lt;add(3,5)&lt;&lt;endl;<br />&nbsp;&nbsp;&nbsp;getchar();<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;<br />}</div>6，在工程-&gt;属性，链接中，添加刚才生成的lib，我工程生成的lib文件是testlib，如下：<br /><img src="http://www.cppblog.com/images/cppblog_com/mycblog/vs2010环境下生成lib文件2.png" width="851" height="599" alt="" /><br />7，运行的结果如下：<br /><img src="http://www.cppblog.com/images/cppblog_com/mycblog/vs2010环境下生成lib文件3.png" width="678" height="440" alt="" /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"></div><img src ="http://www.cppblog.com/MyCBlog/aggbug/164901.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-03 17:46 <a href="http://www.cppblog.com/MyCBlog/articles/164901.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>dll与lib的区别</title><link>http://www.cppblog.com/MyCBlog/articles/164892.html</link><dc:creator>绿</dc:creator><author>绿</author><pubDate>Fri, 03 Feb 2012 08:30:00 GMT</pubDate><guid>http://www.cppblog.com/MyCBlog/articles/164892.html</guid><wfw:comment>http://www.cppblog.com/MyCBlog/comments/164892.html</wfw:comment><comments>http://www.cppblog.com/MyCBlog/articles/164892.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MyCBlog/comments/commentRss/164892.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MyCBlog/services/trackbacks/164892.html</trackback:ping><description><![CDATA[<div><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">静态链接库和动态链接库的区别：</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">1.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">如果采用静态链接库，lib中的指令都包含在最终生成的exe文件中。如果采用动态的链接库，该dll不必包含在exe文件中。Exe文件执行时，可以动态的加载和卸载这个与exe无关的dll文件。</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">2.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">静态链接库不能再包含其他的动态链接库或者静态链接库；而动态链接库不受限制，仍然可以包含其他的动态链接库和静态链接库。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'宋体'; ">VC的动态链接库有三种类型，分别是非MFCdll，MFCdll和MFC扩展dll</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">1.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">非MFCdll不采用mfc类库结构，其导出结果为标准的C接口，能为非MFCdll和MFCdll调用。</span></p><p style="margin-left:21.2500pt; text-indent:-21.2500pt; margin-bottom:0pt; margin-top:0pt; "><span style=" font-size:10.5000pt; font-family:'Times New Roman'; ">2.&nbsp;</span><span style=" font-size:10.5000pt; font-family:'宋体'; ">MFCdll包含一个继承CWinApp的类，但其无消息循环，MFC扩展dll采用MFC动态链接版本创建，它只能被用MFC类库所编写的应用程序调用。</span></p><p style="margin-bottom:0pt; margin-top:0pt; "></p><p style="margin-bottom:0pt; margin-top:0pt; "></p><p style="margin-bottom:0pt; margin-top:0pt; "></p></div><img src ="http://www.cppblog.com/MyCBlog/aggbug/164892.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MyCBlog/" target="_blank">绿</a> 2012-02-03 16:30 <a href="http://www.cppblog.com/MyCBlog/articles/164892.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>