﻿<?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++博客-xiaoU's blog-随笔分类-3.C/C++</title><link>http://www.cppblog.com/xiaouisme/category/7145.html</link><description>                     &amp;nbsp;       &amp;nbsp;       &amp;nbsp;       &amp;nbsp;       &amp;nbsp;       &amp;nbsp;       &amp;nbsp;       &amp;nbsp;       &amp;nbsp;       &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;       &amp;nbsp;       &amp;nbsp;       &amp;nbsp;       &amp;nbsp;       &amp;nbsp;       &amp;nbsp;       &amp;nbsp;         我是大兴安岭动物园猫科动物小鼬uuuuu</description><language>zh-cn</language><lastBuildDate>Thu, 03 Dec 2009 07:35:06 GMT</lastBuildDate><pubDate>Thu, 03 Dec 2009 07:35:06 GMT</pubDate><ttl>60</ttl><item><title>为什么VS监视的函数地址和输出的函数地址不同？</title><link>http://www.cppblog.com/xiaouisme/archive/2009/12/03/102455.html</link><dc:creator>小鼬</dc:creator><author>小鼬</author><pubDate>Thu, 03 Dec 2009 04:51:00 GMT</pubDate><guid>http://www.cppblog.com/xiaouisme/archive/2009/12/03/102455.html</guid><wfw:comment>http://www.cppblog.com/xiaouisme/comments/102455.html</wfw:comment><comments>http://www.cppblog.com/xiaouisme/archive/2009/12/03/102455.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xiaouisme/comments/commentRss/102455.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xiaouisme/services/trackbacks/102455.html</trackback:ping><description><![CDATA[<p>为什么VS监视的函数地址和输出的函数地址不同？</p>
<p>#include&lt;iostream&gt;<br>using namespace std;<br>void gf(){ cout&lt;&lt;"::gf()"; }<br>typedef void(*F)();<br>int main()<br>{ <br>&nbsp;&nbsp;&nbsp; gf();<br>&nbsp;&nbsp;&nbsp; F f=gf;<br>&nbsp;&nbsp;&nbsp; printf("%p&nbsp; \n",f);//输出的是00434F55<br>&nbsp;&nbsp;&nbsp; system("pause");<br>}</p>
<p>VS2005下断点，添加监视：<br><img src="http://www.cppblog.com/images/cppblog_com/xiaouisme/232.jpg" border=0><br><br><font color=#f70997>为什么输出的函数地址和VS监视到的不同？<br></font>答：<font color=#3809f7>输出的是跳转指令的地址,监视到的是函数地址.<br>两条指令紧挨着执行，一般输出的都是跳转表的地址，而不是函数的绝对地址</font></p>
<p><br>以下是VS下断点后，调试/窗口/反汇编 显示的汇编代码：<br>&#8230;&#8230;<br>;跳转表：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （本行是本人加的）<br>std::locale::id::operator unsigned int:<br>00434F50&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::locale::id::operator unsigned int (43D8F0h) <br>gf:<br><strong>00434F55&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gf (4377C0h)</strong>&nbsp; <br>DName::isValid:<br>00434F5A&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DName::isValid (4845D0h) <br>&#8230;&#8230;<br>void gf(){ cout&lt;&lt;"::gf()"; }<br><strong>004377C0</strong>&nbsp; push&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ebp&nbsp; <br>004377C1&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ebp,esp <br>&#8230;&#8230;<br>gf();<br>0043783E&nbsp; <strong>call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gf (434F55h) <br></strong>F f=gf;<br>00437843&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [f],offset gf (434F55h) <br>&#8230;&#8230;<br>system("pause");<br>0043785B&nbsp; push&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offset string "pause" (4A2098h) <br>00437860&nbsp; call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @ILT+2850(_system) (434B27h) <br>00437865&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; esp,4 <br>&#8230;&#8230;</p>
<img src ="http://www.cppblog.com/xiaouisme/aggbug/102455.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xiaouisme/" target="_blank">小鼬</a> 2009-12-03 12:51 <a href="http://www.cppblog.com/xiaouisme/archive/2009/12/03/102455.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编译时、运行时调通过指针将用到哪个虚函数、非虚函数、成员变量</title><link>http://www.cppblog.com/xiaouisme/archive/2009/12/03/102454.html</link><dc:creator>小鼬</dc:creator><author>小鼬</author><pubDate>Thu, 03 Dec 2009 04:39:00 GMT</pubDate><guid>http://www.cppblog.com/xiaouisme/archive/2009/12/03/102454.html</guid><wfw:comment>http://www.cppblog.com/xiaouisme/comments/102454.html</wfw:comment><comments>http://www.cppblog.com/xiaouisme/archive/2009/12/03/102454.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xiaouisme/comments/commentRss/102454.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xiaouisme/services/trackbacks/102454.html</trackback:ping><description><![CDATA[<table style="TABLE-LAYOUT: fixed" cellSpacing=0 cellPadding=0 width="99%" border=0>
    <tbody>
        <tr>
            <td class=logt><span id=ob_logd153></span>
            <p>#include&lt;iostream&gt;<br>using namespace std;</p>
            <p>class A{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char c;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void f(){cout&lt;&lt;"A::f()"&lt;&lt;endl;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual void vf(){cout&lt;&lt;"A::vf()"&lt;&lt;endl;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A():i(11){}<br>}a;</p>
            <p>class B{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void f(){cout&lt;&lt;"B::f()"&lt;&lt;endl;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual void vf(){cout&lt;&lt;"B::vf()"&lt;&lt;endl;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int c;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B():i(22),c(66){}<br>}b;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
            <p>int main(){&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; A *pA=(A*)&amp;b;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; pA-&gt;f();/<font color=#2222dd>*编译时就决定了调用A::f()。因为不是虚函数，不存在"运行时决定类型"。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(所谓运行时决定类型，其实就是在调用虚函数时，将根据对象的内存地址来偏移，找到虚函数表。。。)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;类的非虚成员函数其实是全局函数（因此，就存储空间而言，它&#8221;不属于&#8220;类），调用时根据隐<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;含指针this来决定调用哪个，其实就是全局的重载函数——根据形参决定调用版本。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这里传递的是A类指针，当然调用的是void f(A* this) 这个版本。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因此，编译时就确定了调用的哪个函数。&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;为什么不在运行时决定？因为它&#8221;不属于&#8220;类，它是全局的，不可能根据类对象地址来偏移来寻址。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *</font>/<br>&nbsp;&nbsp;&nbsp; cout&lt;&lt;pA-&gt;i&lt;&lt;endl;/<font color=#1a1ae6>*编译时认为将输出A::i,但是运行时根据类对象寻址类成员变量，<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 输出的其实是:int(b对象的地址 ＋ a对象中i相对于&amp;a的偏移)。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为什么要在运行时决定？因为它是&#8220;属于&#8221;类的，要根据类对象的地址来偏移寻址。<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;pA-&gt;b&lt;&lt;endl;编译时认为将输出A::b,所以编译出错："class A has no member named 'b' <br></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;*/&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; pA-&gt;vf();/<font color=#3d11ee>*运行时决定。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 他是怎么做到运行时决定的呢？魔术，说穿了，所谓&#8220;运行时动态类型&#8221;根本就是一个障眼法。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;编译时，调用什么并不知道，只知道调用的是一个虚函数，因此，根据指针指向的对象——b来寻址，（其实，此刻它仍然把pA指向的b当作A类对象，但是同一个编译器下虚表相对于对象起始地址的偏移是编译器已经确定了的。）找到虚函数表地址（虚表是在类内部的），然后根据虚表找到虚函数地址。</font><font color=#3d11ee><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 因此，&#8220;运行时决定&#8221;的立足点是虚函数。 <br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;*/&nbsp;&nbsp;&nbsp; <br></font>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; cout&lt;&lt;"\n------------------&gt;"&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; cout&lt;&lt;sizeof b&lt;&lt;"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;"&lt;&lt;sizeof a&lt;&lt;endl;&nbsp;<font color=#3d11ee>/*VC中，类对象各成员的存储顺序依次为：虚表（如果有则）4字节，非静态成员变量按声明顺序依次（默认4字节对齐）。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 静态成员和成员函数都不在类对象的&#8220;内部&#8221;*/</font><br>&nbsp;&nbsp;&nbsp; cout&lt;&lt;int(*&nbsp; ((char*)&amp;b+4)&nbsp; )&lt;&lt;endl; <br>&nbsp;&nbsp;&nbsp; cout&lt;&lt;int(*&nbsp; ((char*)&amp;b+8)&nbsp; )&lt;&lt;endl; <br>&nbsp;&nbsp;&nbsp; typedef void(*F)();<br>&nbsp;&nbsp;&nbsp; F ff= (F)*(&nbsp;&nbsp; (int*)*(int*)&amp;b +0&nbsp;&nbsp; ) ;<br>&nbsp;&nbsp;&nbsp; ff();<br>&nbsp;&nbsp;&nbsp; cout&lt;&lt;"&lt;------------------\n"&lt;&lt;endl;<br><br>&nbsp;&nbsp;&nbsp; system("pause");<br>}</p>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/xiaouisme/aggbug/102454.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xiaouisme/" target="_blank">小鼬</a> 2009-12-03 12:39 <a href="http://www.cppblog.com/xiaouisme/archive/2009/12/03/102454.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>