<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>DraculaW</title>
    <description></description>
    <link>http://draculaw.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>如何使VC2008E支持ATL\WTL</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/194305" style="color:red;">http://draculaw.javaeye.com/blog/194305</a>&nbsp;
          发表时间: 2008年05月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>微软发布了最新的vc2008， 像05一样他也发布了Express版本供大家下载试玩， 不过很郁闷的是这个版本竟然不支持ATL 与MFC, 而我最近对ATL\WTL很有兴趣。怎么办呢？自己DIY一个支持ATL\WTL的VC2008E吧。<br /><br />首先 我们发现 他这里面没有ATL的源文件和lib 于是我们去其他地方找到了（找一个装着带有ATL的VC） include\atlmfc文件夹下面就是了<br />把它拷过来， 添加到include,src和lib里面去<br />现在就可以写atl的程序了哦<br /><br />然后我们去下载WTL8.0的文件， 解压后，找到appwiz 在里面吧vs80x.js里面8.0的版本都改为9.0。 <br /><br />然后打开他的sample。 </p>
<p>编译， 有个error. 研究一下 发现是一个为VC2005设计的宏，注释掉</p>
<p>ok 可以编译通过了</p>
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/194305#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 19 May 2008 11:21:02 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/194305</link>
        <guid>http://draculaw.javaeye.com/blog/194305</guid>
      </item>
      <item>
        <title>传一个数组的引用</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/192396" style="color:red;">http://draculaw.javaeye.com/blog/192396</a>&nbsp;
          发表时间: 2008年05月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>我们知道&nbsp;给一个函数传入一个数组的时候需要传入一个附加的参数&nbsp;用来标示数组的大小</p>
<p>&nbsp;</p>
<pre name="code" class="java">void print(const unsigned short * const p, const size_t n) {     cout &lt;&lt; "sizeof(p): " &lt;&lt; sizeof(p) &lt;&lt; endl;      for (size_t i = 0; i &lt; n; ++i) {         cout &lt;&lt; p[i] &lt;&lt; endl;     } }  int main() {     const unsigned short a[] = { 11, 22, 33, 44, 55 };      cout &lt;&lt; "sizeof(a): " &lt;&lt; sizeof(a) &lt;&lt; endl;     cout &lt;&lt; "sizeof(a[0]): " &lt;&lt; sizeof(a[0]) &lt;&lt; endl;      print(a, sizeof(a) / sizeof(a[0])); } </pre>
<p>&nbsp;</p>
<p>有没有什么办法不传入这个，&nbsp;对了&nbsp;就是数组的引用</p>
<p>&nbsp;</p>
<p>&nbsp;
<pre name="code" class="java">void print(const unsigned short (&amp; r)[5]) {
    cout &lt;&lt; "sizeof(r): " &lt;&lt; sizeof(r) &lt;&lt; endl;

    for (size_t i = 0; i &lt; sizeof(r) / sizeof(r[0]); ++i) {
        cout &lt;&lt; r[i] &lt;&lt; endl;
    }
}

int main() {
    const unsigned short a[] = { 11, 22, 33, 44, 55 };

    print(a);
}
</pre>
</p>
<p>&nbsp;讲引用传入之后 也就讲数组的所有信息传入了， 可以用这样的方法把数组的大小来传入，</p>
<p>可是这样子还是很不好办，因为要是为每个长度的数组都写一个这样的函数，那我们就累都累死了..</p>
<p>该怎么办呢，&nbsp;对了&nbsp;我们想到了一个好的方法&nbsp;模板</p>
<p>
<pre name="code" class="cpp">template &lt;typename T, size_t N&gt; void print(const T (&amp; r)[N]) {
    for (size_t i = 0; i &lt; N; ++i) {
        cout &lt;&lt; r[i] &lt;&lt; endl;
    }
}

int main() {
    const int c[] = { 1, 2, 4, 8 };

    print(c);

    const double d[] = { 3.14159, 2.71828, .57722 };

    print(d);
}
</pre>
</p>
<p>好的， 这样子看起来问题已经得到了很好的解决</p>
<p>可是熟悉模板的人一看就看出来问题了：如果这个函数的长度比较大，那么我们还是会在编译的时候为每个长度的数组创建一个函数，生成文件的大小还是会比较大，这么该怎么办呢？联想到了type_trails, 我们也可以做一个差不多的东西</p>
<p>
<pre name="code" class="cpp">template &lt;typename T, size_t N&gt; size_t length(const T (&amp;)[N]) {
    return N;
}
</pre>
&nbsp;</p>
<p>&nbsp;代码简单，尽量减少了需要的大小，应该来说是最好的解决方案了。为什么要说应该来说呢吗因为我们没用到STL 如果用到STL 中的Vector, 那么这么多事情我们也就不用来了。 呵呵</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/192396#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 12 May 2008 22:23:54 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/192396</link>
        <guid>http://draculaw.javaeye.com/blog/192396</guid>
      </item>
      <item>
        <title>深入浅出设计模式 读书笔记之 策略模式</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/191610" style="color:red;">http://draculaw.javaeye.com/blog/191610</a>&nbsp;
          发表时间: 2008年05月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><span style="font-family: 宋体;"><span style="font-size: medium;"><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">策略模式</span><span style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"> <span lang="EN-US"></span></span></span></span></p>
<p><span style="font-family: 宋体;"><span style="font-size: medium;"><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">其实我觉得介绍不需要太多</span><span style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"> </span><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">因为大家都已经很熟悉这个模式了，</span><span style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"> <span lang="EN-US"></span></span></span></span></p>
<p><span style="font-family: 宋体;"><span style="font-size: medium;"><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">一个实体类</span><span style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"> </span><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">保存一个对策略的接口，</span><span style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"> <span lang="EN-US"></span></span></span></span></p>
<p><span style="font-family: 宋体;"><span style="font-size: medium;"><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">一个策略接口</span><span style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"> </span><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">定义策略的公共接口</span><span lang="EN-US" style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"></span></span></span></p>
<p><span style="font-family: 宋体;"><span style="font-size: medium;"><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">策略的实现</span><span style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"> </span><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">对接口的实现</span><span style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"> <span lang="EN-US"></span></span></span></span></p>
<p><span style="font-family: 宋体;"><span style="font-size: medium;"><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">关于策略模式的</span><span lang="EN-US" style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">UML</span><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">类图我也就不画了，在网上一搜就是一大堆。</span><span lang="EN-US" style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"></span></span></span></p>
<p><span lang="EN-US" style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"><span style="font-size: medium; font-family: 宋体;">&nbsp;</span></span></p>
<p><span style="font-family: 宋体;"><span style="font-size: medium;"><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">我想说的是，其实策略模式主要就是面向对象的一个重要的基本方法，首先考虑组合然后是公共继承。</span><span lang="EN-US" style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"></span></span></span></p>
<p><span style="font-family: 宋体;"><span style="font-size: medium;"><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">这段话在很多书里面都有出现过。但是我们大家很少有这么样思考的。一般来说开始都是继承继承，一个基类不行再加一个接口，就像书中所演示的，一个鸭子的类，可以用这么复杂的继承，那么如果是人类的话估计这个就复杂的无法收拾了。</span><span style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"> </span><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">这就是基本的方法的重要性。</span><span lang="EN-US" style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"></span></span></span></p>
<p><span lang="EN-US" style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"><span style="font-size: medium; font-family: 宋体;">&nbsp;</span></span></p>
<p><span style="font-family: 宋体;"><span style="font-size: medium;"><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">以后设计的时候一定要注意根据</span><span lang="EN-US" style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">OO</span><span style="font-size: 8pt; color: black; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana;">的基本方法来思考而不是根据自己不好的习惯来，争取把好的方法作为自己的习惯，这样子才能写出更好的软件来</span><span lang="EN-US" style="font-size: 8pt; color: black; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"></span></span></span></p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/191610#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 09 May 2008 23:26:18 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/191610</link>
        <guid>http://draculaw.javaeye.com/blog/191610</guid>
      </item>
      <item>
        <title>將foobar的播放列表中的文件整理起來的perl代碼</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/157525" style="color:red;">http://draculaw.javaeye.com/blog/157525</a>&nbsp;
          发表时间: 2008年01月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="perl">
# The readfpl accept a file's path while is fpl(foobar play list),
# and return a list which holds all the file'path
sub readfpl
{
    my @files;
    my @chunks;
    my $index = 0;

    open(INPUT, "&lt; $_[0]")
        or die "can't open";

    @chunks = split(m{file://}, &lt;INPUT>);

    foreach(@chunks)
    {   
        if($_ =~ m/.+\.(mp3|wma|m4a)/)
        {
            $files[$index] = $&;
            $index ++;
        }
    }

    print $files[0];
   
    return @files;
}

my @files = readfpl($ARGV[0]);
my $string;

foreach(@files){
     $string = $_;
        # the next while get name from path
     while( substr($string, 1) =~ m{\\.+\.(mp3|wna|m4a)}) {
         $string = $ARGV[0].$&;
         }
     rename $_, string;
}
</pre><br /><br />將這段代碼存為movefpl.pl然后在命令行打入 movefpl.pl 播放列表的全路徑 要存歌曲的新路徑
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/157525#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 19 Jan 2008 00:21:51 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/157525</link>
        <guid>http://draculaw.javaeye.com/blog/157525</guid>
      </item>
      <item>
        <title>红黑树</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/160285" style="color:red;">http://draculaw.javaeye.com/blog/160285</a>&nbsp;
          发表时间: 2007年12月02日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>&nbsp;关于红黑树的定义：</p><p>红黑树的定义 <br />1 节点不是红的就是黑的<br />2 根节点和叶子节点为黑的<br />3 红色节点的父亲节点是黑的<br />4 从根节点到叶子节点 走过的黑色节点的数目是相同的<br /><br />红黑树是一种比较复杂的数据结构 复杂的地方在于他的插入和删除后的平衡问题</p><p>在插入时 的平衡：</p><p>1 插入的是红色的节点<br />2 如果它的父亲是黑色的 就做第八步<br />3 如果它的父亲是红色的而且它有叔叔节点也为红色的 那么把他的父亲和叔叔节点都设为黑色的 祖父节点设为红色的 然后对爷爷 重新进行第2步<br />4 如果他没有树树节点或者叔叔节点为黑色 那么再看 如果他相对于父亲的位置与父亲相对于祖父的位置 如果一致 走到第6 <br />5 如果不一致 那么对他于他的父亲节点进行轮转 转到一致 然后 再把指向它的指针指向他的父亲节点<br />6 然后把现在指针指向的节点的父亲（由于他已经与父亲换位了，父亲是它）设为黑色， 爷爷设为红色<br />7 然后再对爷爷重新进行第二步<br />8 确保根节点为黑色的</p><p>呵呵 其实想起来很简单 就是要把插入的节点的祖父节点这个部分平衡后然后再迭代到他的上一级把他们平衡后就好了 </p><p>&nbsp;</p><p>而删除的平衡代码更复杂一点</p><p>删除是找到比删除节点大也仅比删除的节点大的那个节点</p><p>然后进行平衡</p><p>首先 如果用来替换的节点的左儿子是红的 那么把它弄黑 这样子就平了<br />如果是黑色的话 那么看他的新的兄弟的颜色 如果他的兄弟是红的的话 那么 简单 把他的兄弟弄黑 然后他们的老爹弄红再左转他的老爹， 这个样子这个大环境就平了 再去看他们的小环境</p><p>如果他的兄弟是黑色的 而两个儿子都是红色的 那也简单俩儿子都弄黑 他的兄弟弄红 小环境就好了 再去看他的大环境</p><p>后面的两个复杂一些 <br />如果他的兄弟是黑色的 他的兄弟靠近他的儿子是红色的话 那么把他的兄弟弄红 这个儿子弄黑再把这个儿子和他的兄弟进行轮转 凑成下面的情况<br /><br />现在他的兄弟是黑色的了 而他的兄弟的和他比较远的儿子是红色的 现在 把它的兄弟和老爹进行换色 他的兄弟的那个和他比较远的儿子弄成黑色 &nbsp;然后轮转他的兄弟和老爹 哈哈 现在是平的了 &nbsp;<br /></p>
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/160285#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 02 Dec 2007 22:05:00 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/160285</link>
        <guid>http://draculaw.javaeye.com/blog/160285</guid>
      </item>
      <item>
        <title>Best Fit与 First Fit</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/160286" style="color:red;">http://draculaw.javaeye.com/blog/160286</a>&nbsp;
          发表时间: 2007年12月02日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          内存分配的两种方式 <br />UNIX System V的malloc使用的是 first fit 为此 我一直觉得很奇怪 为啥 为啥 有best不用 为啥要用那个first 奇怪<br />为此我傻瓜了好久 <br /><br />今天 项目空闲时 想明白了 呵呵<br />因为 我们不一定能找到最适合的大小的内存 可能每次还都是会有些碎片的 <br />如果使用best fit 万一每次都没有找到的话 那么每次产生的碎片都是最小的 这样的碎片可能对以后都没有什么用处了<br />而如果使用first fit 就不会每次都产生最小的碎片 而是产生的碎片可能比较大 下次申请的时候&nbsp; 可能这么段刚好给它用了 完美<br /><br />而且还有效率的考虑 如果4G的内存 每次分配都遍历一次 那么多次分配 速度可能就太差了 而first就没有这个问题&nbsp;&nbsp;
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/160286#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 02 Dec 2007 12:29:00 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/160286</link>
        <guid>http://draculaw.javaeye.com/blog/160286</guid>
      </item>
      <item>
        <title>汇编学习 1 寄存器的作用 寻址方式</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/160287" style="color:red;">http://draculaw.javaeye.com/blog/160287</a>&nbsp;
          发表时间: 2007年11月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          首先 是寄存器的介绍<br /> <br /> 寄存器名&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;  功能<br /> eax:&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;  加法乘法指令的缺省寄存器, 函数返回值<br /> ecx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  计数器&nbsp;&nbsp;                        REP &amp; LOOP指令的内定计数器<br /> edx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;  除法寄存器   &nbsp;&nbsp;              存放整数除法产生的余数<br /> ebx  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;      基址寄存器            &nbsp;&nbsp;  &nbsp;&nbsp;  在内存寻址时存放基地址<br /> esp   &nbsp;&nbsp;&nbsp;&nbsp;      栈顶指针寄存器            SS：ESP当前堆栈的栈顶指针<br /> ebp&nbsp;&nbsp;        &nbsp;&nbsp;  栈底指针寄存器            SS：EBP当前堆栈的栈底指针<br /> esi, edi   &nbsp;&nbsp;  源、目标索引寄存器  &nbsp;&nbsp;  在字符串操作指令中，DS：ESI指向源串 ES：EDI指向目标串<br /> //以上为通用寄存器<br /> eip &nbsp;&nbsp;        &nbsp;&nbsp;  指令寄存器&nbsp;&nbsp;                  CS:EIP指向下一条指令的地址 (也叫PC)<br /> eflags     &nbsp;&nbsp;  标志寄存器&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  标志寄存器<br /> cs&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  代码段寄存器&nbsp;&nbsp;            &nbsp;&nbsp;  当前执行的代码段<br /> ss              椎栈段寄存器&nbsp;&nbsp;            &nbsp;&nbsp;  stack segment, 当前堆栈段<br /> ds           &nbsp;&nbsp;  数据段寄存器               data segment, 当前数据段<br /> <br /> <br /> 然后是 寻址方式<br /> <br /> 1 直接寻址方式 <br /> 直接访问内存地址<br /> <br /> 2:寄存器间接寻址方式: <br /> 通过寄存器中存储的内存地址访问内存<br /> <br /> 3 寄存器相对寻址方式:<br /> 将寄存器中内存地址加上一个数值后作为地址访问内存<br /> <br /> 4:基址变址寻址方式: <br /> 把一个基址寄存器（EBX或EBP）的内容加上变址寄存器（ESI或EDI）的内容构成有效地址的寻址方式。若基址寄存器使用EBX，其默认段为数据段DS；若基址寄存器使用EBP，其默认段为堆栈段SS<br /> <br /> 5:相对基址变址寻址方式: <br /> 就是基址变址寻址方式得出的地址再加上一个数值然后进行寻址 譬如[EBX + EDI + 100]<br /> <br /> 一些基础 再加上指令的基础 就可以读懂基本的汇编语句 可以进行debug和写程序了&nbsp;
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/160287#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 15 Nov 2007 20:18:00 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/160287</link>
        <guid>http://draculaw.javaeye.com/blog/160287</guid>
      </item>
      <item>
        <title>boost::type_traits</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/160288" style="color:red;">http://draculaw.javaeye.com/blog/160288</a>&nbsp;
          发表时间: 2007年11月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          与STL的实现不同 在boost中 他们使用的是模板片特化来实现的type traits<br /> 基本思想就是 默认大部分都不支持某种特性 然后 当某个类型支持时就为他特化一个类 支持这样的特性 <br /> 感觉这样写的话 在特化的时候会不会代码会比较多呢 ...<br /> 具体就是 <br /> template&lt;typename T&gt;<br /> class something<br /> {<br /> // 在这里写对广大的类的操作<br /> }<br /> <br /> 然后对于特殊的类型 譬如说 int<br /> template&lt;&gt;<br /> class something&lt;int&gt;<br /> {<br /> //然后在这里写对Int做的特殊的操作 <br /> }<br /> <br /> 而为了type traits来说 它的特殊操作就是在泛型类里面做一个枚举 值为false而在 int里面这个值为true<br /> 那么 当算法来用这个对象时 可以根据这个枚举的值来选择相应的算法 ，譬如对int的速度比较快的 或者对泛型的正确的算法<br /> <br /> 下面是 std::swap的一个优化版本<br /> <br /> //<br /> // iter_swap:<br /> // tests whether iterator is a proxying iterator or not, and<br /> // uses optimal form accordingly:<br /> //<br /> namespace detail{<br /> template &lt;typename I&gt;<br /> static void do_swap(I one, I two, const boost::false_type&amp;)<br /> {<br /> &nbsp;&nbsp;&nbsp;  typedef typename std::iterator_traits&lt;I&gt;::value_type v_t;<br /> &nbsp;&nbsp;&nbsp;  v_t v = *one;<br /> &nbsp;&nbsp;&nbsp;  *one = *two;<br /> &nbsp;&nbsp;&nbsp;  *two = v;<br /> }<br /> template &lt;typename I&gt;<br /> static void do_swap(I one, I two, const boost::true_type&amp;)<br /> {<br /> &nbsp;&nbsp;&nbsp;  using std::swap;<br /> &nbsp;&nbsp;&nbsp;  swap(*one, *two);<br /> }<br /> }<br /> <br /> template &lt;typename I1, typename I2&gt;<br /> inline void iter_swap(I1 one, I2 two)<br /> {<br /> &nbsp;&nbsp;&nbsp;  //<br /> &nbsp;&nbsp;&nbsp;  // See is both arguments are non-proxying iterators,<br /> &nbsp;&nbsp;&nbsp;  // and if both iterator the same type:<br /> &nbsp;&nbsp;&nbsp;  //<br /> &nbsp;&nbsp;&nbsp;  typedef typename std::iterator_traits&lt;I1&gt;::reference r1_t;<br /> &nbsp;&nbsp;&nbsp;  typedef typename std::iterator_traits&lt;I2&gt;::reference r2_t;<br /> &nbsp;&nbsp;&nbsp;  typedef boost::integral_constant&lt;bool,<br /> &nbsp;&nbsp;&nbsp;  ::boost::is_reference&lt;r1_t&gt;::value<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &amp;&amp; ::boost::is_reference&lt;r2_t&gt;::value<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &amp;&amp; ::boost::is_same&lt;r1_t, r2_t&gt;::value&gt; truth_type;<br /> <br /> &nbsp;&nbsp;&nbsp;  detail::do_swap(one, two, truth_type());<br /> }<br /> <br /> 其中 boost::integral_constant&lt;bool,  ::boost::is_reference&lt;r1_t&gt;::value<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &amp;&amp; ::boost::is_reference&lt;r2_t&gt;::value<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &amp;&amp; ::boost::is_same&lt;r1_t, r2_t&gt;::value&gt; truth_type<br /> 就是一个枚举 看传入的参数是否可以用std::swap 如果可以则连接到std::swap不然就用自己写的 呵呵&nbsp;
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/160288#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 13 Nov 2007 23:13:00 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/160288</link>
        <guid>http://draculaw.javaeye.com/blog/160288</guid>
      </item>
      <item>
        <title>STL Type Traits</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/160289" style="color:red;">http://draculaw.javaeye.com/blog/160289</a>&nbsp;
          发表时间: 2007年11月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          &nbsp;模板的引入 使c++产生了泛型的算法 泛型的容器 <br /> 这两个是个好东西 但是在将两项技术结合的时候产生了一个问题  就是在写程序的时候要暴露对象的类型<br /> 就像这个样子 :<br /> template&lt;typename T&gt;<br /> vector&lt;T&gt;::iterator find(const T&amp; )<br /> {<br /> ........<br /> }<br />  而如果暴露了类型的话 那么就不能写一段代码而完成问题了 必须为每种容器都写出相同的算法 <br /> 怎么办呢 可以在find中传出两个参数<br /> template&lt;typename T&gt;<br /> vector&lt;T&gt;::iterator find(const T&amp;, T&amp; result )<br /> {<br /> ........<br /> }<br /> 但是好像还是有问题 譬如类型的引用 还有size 指针 等等 都是不同的类型 写起来还是很头大<br /> 于是 聪明的人们想出了type traits这项技术<br /> 这项技术<br /> typename&lt;typename T&gt;<br /> class iterator<br /> {<br /> public:<br /> &nbsp;&nbsp;&nbsp;  typedef T value_type<br /> }<br /> typename&lt;typename I&gt;<br /> typename I::value_type<br /> find(I &amp;)<br /> {<br /> }<br /> PS ：注意 这个传入的I是一个迭代器哦 <br /> 我们把他需要传回的值 现在 所有的问题就都解决了呢 <br /> <br /> 可能写的比较混乱 但是大概也能明白那个意思吧 ...
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/160289#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 13 Nov 2007 23:09:00 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/160289</link>
        <guid>http://draculaw.javaeye.com/blog/160289</guid>
      </item>
      <item>
        <title>使用模板实现转换测试</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/160290" style="color:red;">http://draculaw.javaeye.com/blog/160290</a>&nbsp;
          发表时间: 2007年08月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          template&lt;typename T, typename U&gt;<br /> class Conversion<br /> {<br /> &nbsp;&nbsp;&nbsp; typedef char Small;<br /> &nbsp;&nbsp;&nbsp; class Big{char dummy[2];};<br /> &nbsp;&nbsp;&nbsp; static Small Test(U)&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;  }&nbsp;&nbsp;  <br /> &nbsp;&nbsp;&nbsp; static Big Test(...)&nbsp; { }&nbsp;&nbsp;  <br /> &nbsp;&nbsp;&nbsp; static T MakeT()&nbsp; {&nbsp; }<br /> &nbsp;&nbsp;&nbsp; <br /> public:<br /> &nbsp;&nbsp;&nbsp; enum { exists = sizeof(Test(MakeT())) == sizeof(Small)};&nbsp;&nbsp;&nbsp; <br /> };<br /> <br /> 不得不承认 发明这段代码的人很有才...<br /> <br /> 如果T可以转换为U 于是调用Test(MakeT())会连到Test(U)这个函数 返回一个char；<br /> 如果不能 就调用使用(...)缺省参数的函数&nbsp; 返回一个数组<br /> <br /> 然后对返回值进行判断....<br /> 这样的代码 看起来很容易 自己却很难去想象出来....<br /> &nbsp;
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/160290#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 14 Aug 2007 16:29:00 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/160290</link>
        <guid>http://draculaw.javaeye.com/blog/160290</guid>
      </item>
      <item>
        <title>原来我一直在脱了裤子放屁啊 NULL指针可以直接delete哦</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/160291" style="color:red;">http://draculaw.javaeye.com/blog/160291</a>&nbsp;
          发表时间: 2007年08月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在某坛子里面逛 看到有些人再批 <br />if( p == NULL ) delete p;<br />p = NULL;<br /><br />很好奇的看了下去 <br />原来 delete 和 free都是支持NULL指针的啊<br /><br /><div class="msgborder">&nbsp; <strong>C99 7.20.3.2 The free function</strong><br /> The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. <strong>If ptr is a null pointer, no action occurs.<br /><br /></strong><strong> C++98 5.3.5 Delete</strong><br /> if the value of the operand of delete is the <strong>null pointer</strong> the operation has <strong>no effect</strong>.</div>
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/160291#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 10 Aug 2007 10:46:00 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/160291</link>
        <guid>http://draculaw.javaeye.com/blog/160291</guid>
      </item>
      <item>
        <title>善用STL,节约代码量</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/160292" style="color:red;">http://draculaw.javaeye.com/blog/160292</a>&nbsp;
          发表时间: 2007年08月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在csdn上大家寫出了各種方式-@-可是...  都太復雜了 如<br /> 1 ：<br /> <br /> void replace(char *pInput, char *pOutput, char *pSrc, char *pDst) <br /> { <br /> char *pi, *po, *p; <br /> int nSrcLen, nDstLen, nLen; <br /> <br /> pi = pInput;  <br /> po = pOutput; <br /> nSrcLen = strlen(pSrc); <br /> nDstLen = strlen(pDst); <br /> <br /> p = strstr(pi, pSrc); <br /> if(p) <br /> { <br /> while(p) <br /> { <br /> nLen = (int)(p - pi); <br /> memcpy(po, pi, nLen); <br /> memcpy(po + nLen, pDst, nDstLen); <br /> pi = p + nSrcLen; <br /> po = po + nLen + nDstLen; <br /> p = strstr(pi, pSrc); <br /> }  <br /> strcpy(po, pi); <br /> } <br /> else <br /> { <br /> strcpy(po, pi); <br /> } <br /> } <br /> <br /> 2<br /> <br /> Fun(char *A, char *B, char *C)<br /> {<br /> int lenA = strlen(A);<br /> int lenB = strlen(B);<br /> int  lenC = strlen(C);<br /> int  Count = 0;<br /> int j = 0;<br /> int k = 0;<br /> while ((j &lt; lenA) &amp;&amp; (i &lt; lenB))<br /> {<br /> if ( A[j] == B[i] || (A[j] - '32' == B[i]) || (A[j] + '32' == B[i]))<br /> {<br /> j++;<br /> i++;<br /> Count++;             <br /> }<br /> else<br /> {<br /> Count = 0;<br /> i = 0;<br /> j = j - i +1;<br /> }<br /> } <br /> if (j &gt;= lenB)<br /> {<br /> pos = i - lenB;<br /> }<br /> for (;pos &lt; lenB&amp;&amp; Count--; pos++)<br /> {<br /> A[pos] = C[k++]; <br /> }<br /> <br /> }<br /> <br /> 3<br /> <br /> void find_rep(char *a, char *b, char *c)<br /> {<br /> int lena, lenb, lenc;<br /> lena = strlen(a);<br /> lenb = strlen(b);<br /> lenc = strlen(c);<br /> <br /> std::cout &lt;&lt; &quot;a:\t&quot; &lt;&lt; a &lt;&lt;endl<br /> &lt;&lt; &quot;b:\t&quot; &lt;&lt; b &lt;&lt; endl<br /> &lt;&lt; &quot;c:\t&quot; &lt;&lt; c &lt;&lt;endl;<br /> std::cout &lt;&lt; &quot;len:\t&quot; &lt;&lt; lena &lt;&lt; &quot;\t&quot; &lt;&lt; lenb &lt;&lt; &quot;\t&quot; &lt;&lt; lenc &lt;&lt; endl;<br /> <br /> int i, j, k, sanum;<br /> int istore=0;<br /> <br /> for(i=0; i&lt;lena;)<br /> {<br /> sanum=0;<br /> for(j=0; j&lt;lenb&amp;&amp;i&lt;lena;)<br /> {<br /> if(a[i]==b[j]||a[i]+32==b[j]||a[i]-32==b[j])<br /> {<br /> i++;<br /> j++;<br /> sanum++;<br /> }<br /> <br /> else<br /> {<br /> i=i-j+1;<br /> j=0;<br /> sanum=0;<br /> }<br /> }<br /> if(sanum==lenb)<br /> {<br /> istore=i-sanum;         //orin i<br /> j=0;<br /> <br /> for(istore, j; j&lt;lenc; j++,istore++)<br /> a[istore] = c[j];<br /> j=i;//now i<br /> i=i+lenc-lenb;         //next i<br /> for(k=i; k&lt;lena+lenc-lenb; k, j++;)<br /> a[k] = a[j];<br /> a[k] = '\0';<br /> lena = strlen(a);<br /> }<br /> }<br /> std::cout &lt;&lt; a &lt;&lt; endl;<br /> //system(&quot;pause&quot;);<br /> }<br /> <br /> 4 最可愛的就是一個哥們了 他寫的代碼好奇怪 號稱用了STL可是....<br /> <br /> #include &lt;iostream&gt;<br /> #include &lt;vector&gt;<br /> #include &lt;algorithm&gt;<br /> #include &lt;string&gt;<br /> #include &lt;iterator&gt;<br /> <br /> using namespace std;<br /> <br /> class Comp<br /> {<br /> public:<br /> bool operator()( const char&amp; Elem1, const char&amp; Elem2 )<br /> {<br /> return ToUpper(Elem1) == ToUpper(Elem2);<br /> }<br /> <br /> private:<br /> char ToUpper( const char&amp; ch )<br /> {<br /> return ch&gt;='a' &amp;&amp; ch&lt;='z' ? ch-'a' + 'A' : ch;<br /> }<br /> };<br /> <br /> string SearchAndReplace(const string&amp; src, const string&amp; searchment, const string&amp; replacement )<br /> {<br /> vector&lt;string::const_iterator&gt; idxs;<br /> <br /> string::const_iterator it = search( src.begin(), src.end(), <br /> searchment.begin(), searchment.end(), Comp() ) ;<br /> <br /> for( ;<br /> it!= src.end();<br /> it=search( it,  src.end(), <br /> searchment.begin(), searchment.end(), Comp() ) )<br /> {<br /> idxs.push_back( it );<br /> it += searchment.size();<br /> <br /> }<br /> <br /> string result;<br /> string::const_iteratorit_s = src.begin();<br /> for ( vector&lt;string::const_iterator&gt;::iterator it = idxs.begin(); it != idxs.end(); ++it )<br /> {<br /> string::const_iterator it_e = *it;<br /> <br /> copy( it_s, it_e, back_inserter( result ) );<br /> copy( replacement.begin(), replacement.end(), back_inserter( result ) );<br /> <br /> it_s = it_e + searchment.size();<br /> }<br /> <br /> if ( it_s != src.end() )<br /> copy ( it_s, src.end(), back_inserter( result ) );<br /> <br /> return result;<br /> }<br /> <br /> int main()<br /> {<br /> cout&lt;&lt; fun( &quot;aaAbb&quot;, &quot;ab&quot;, &quot;kkk&quot; ) ;<br /> <br /> getchar();<br /> }<br /> <br /> <br /> <strong>當當當當<br /> 正確答案在這里<br /> <br /> string function(string a, string b, string c)<br /> {<br /> &nbsp;&nbsp;&nbsp;  int n = b.size();<br /> &nbsp;&nbsp;&nbsp;    int pos = 0; <br /> &nbsp;&nbsp;&nbsp;  while( (pos = a.find(b,pos)) != -1)<br /> &nbsp;&nbsp;&nbsp;    {<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;       a.replace( pos, n, c );<br /> &nbsp;&nbsp;&nbsp;    }<br /> }</strong>
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/160292#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 07 Aug 2007 09:39:00 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/160292</link>
        <guid>http://draculaw.javaeye.com/blog/160292</guid>
      </item>
      <item>
        <title>bigendian與littleendian的兩種測試方式</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/160293" style="color:red;">http://draculaw.javaeye.com/blog/160293</a>&nbsp;
          发表时间: 2007年08月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          其實只需要這樣一段代碼<br /> &nbsp;&nbsp;&nbsp;  union UA<br /> &nbsp;&nbsp;&nbsp;  {<br /> &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;  int a;<br /> &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;  char c[4];<br /> &nbsp;&nbsp;&nbsp;  }u;<br /> &nbsp;&nbsp;&nbsp;  u.a = 0x12345678;<br /> <br /> &nbsp;&nbsp;&nbsp;  cout &lt;&lt; hex &lt;&lt; (unsigned short)u.c[0] &lt;&lt; endl<br /> &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;  &lt;&lt; hex &lt;&lt; (unsigned short)u.c[1] &lt;&lt; endl<br /> &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;  &lt;&lt; hex &lt;&lt; (unsigned short)u.c[2] &lt;&lt; endl<br /> &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;  &lt;&lt; hex &lt;&lt; (unsigned short)u.c[3] &lt;&lt; endl;<br /> 如果輸出的第一個為 78那么就是小端 如果是12 就是大端。<br /> <br /> 但是  有時候 需要在編譯期 確定 那么就需要用宏來完成:<br /> <br /> 可以根據所用的cpu然后寫可移植的代碼<br /> <br /> #define BYTE_ORDER<br /> <br /> #define LITTLE_ENDIAN 1234<br /> #define BIG_ENDIAN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  4321<br /> <br /> # if( BYTE_ORDER == LITTLE_ENDIAN )<br /> // then little endian<br /> #else<br /> // then bigendian<br /> #endif&nbsp;
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/160293#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 06 Aug 2007 11:44:00 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/160293</link>
        <guid>http://draculaw.javaeye.com/blog/160293</guid>
      </item>
      <item>
        <title>將foobar的播放列表中的文件整理起來的perl代碼</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/160294" style="color:red;">http://draculaw.javaeye.com/blog/160294</a>&nbsp;
          发表时间: 2007年08月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          &nbsp;# The readfpl accept a file's path while is fpl(foobar play list),<br /> # and return a list which holds all the file'path <br /> sub readfpl<br /> {<br /> &nbsp;&nbsp;&nbsp;  my @files;<br /> &nbsp;&nbsp;&nbsp;  my @chunks;<br /> &nbsp;&nbsp;&nbsp;  my $index = 0;<br /> <br /> &nbsp;&nbsp;&nbsp;  open(INPUT, &quot;&lt; $_[0]&quot;)<br /> &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;  or die &quot;can't open&quot;;<br /> <br /> &nbsp;&nbsp;&nbsp;   @chunks = split(m{file://}, &lt;INPUT&gt;);<br /> <br /> &nbsp;&nbsp;&nbsp;  foreach(@chunks)<br /> &nbsp;&nbsp;&nbsp;  {&nbsp;&nbsp;&nbsp;  <br /> &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;  if($_ =~ m/.+\.(mp3|wma|m4a)/)<br /> &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;  {<br /> &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;  $files[$index] = $&amp;;<br /> &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;  $index ++;<br /> &nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;  }<br /> &nbsp;&nbsp;&nbsp;  }<br /> <br /> &nbsp;&nbsp;&nbsp;  print $files[0];<br /> &nbsp;&nbsp;&nbsp;  <br /> &nbsp;&nbsp;&nbsp;  return @files;<br /> }<br /> <br /> my @files = readfpl($ARGV[0]);<br /> my $string;<br /> <br /> foreach(@files){<br /> &nbsp;&nbsp;&nbsp;&nbsp;  $string = $_;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # the next while get name from path<br /> &nbsp;&nbsp;&nbsp;&nbsp;  while( substr($string, 1) =~ m{\\.+\.(mp3|wna|m4a)}) {<br /> &nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;  $string = $ARGV[0].$&amp;;<br /> &nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;  }<br /> &nbsp;&nbsp;&nbsp;&nbsp;  rename $_, string;<br /> }<br /><br /> 將這段代碼存為movefpl.pl然后在命令行打入 movefpl.pl 播放列表的全路徑 要存歌曲的新路徑<br /> 就可以了呢 呵呵
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/160294#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 03 Aug 2007 17:28:00 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/160294</link>
        <guid>http://draculaw.javaeye.com/blog/160294</guid>
      </item>
      <item>
        <title>原來 位移運算的優先級排在加法后面啊</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/160295" style="color:red;">http://draculaw.javaeye.com/blog/160295</a>&nbsp;
          发表时间: 2007年08月01日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          一直以為它在很前面 至少和乘法是一個級別的 <br />唉 看來自己還是很菜很菜的菜鳥
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/160295#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 01 Aug 2007 15:11:00 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/160295</link>
        <guid>http://draculaw.javaeye.com/blog/160295</guid>
      </item>
      <item>
        <title>转载  GDB使用手册</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/160296" style="color:red;">http://draculaw.javaeye.com/blog/160296</a>&nbsp;
          发表时间: 2007年07月31日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span id="ctl00_MainContentPlaceholder_ctl00_ctl00_lblEntry">START-INFO-DIR-ENTRY <br />* Gdb: (gdb).&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The GNU debugger. <br />END-INFO-DIR-ENTRY <br />&nbsp;&nbsp; This file documents the GNU debugger GDB. <br /> <br />&nbsp;&nbsp; This is Edition 4.12, January 1994, of `Debugging with GDB: the GNU <br />Source-Level Debugger' for GDB Version 4.16. <br /> <br />&nbsp;&nbsp; Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995 Free <br />Software Foundation, Inc. <br /> <br />   Permission is granted to make and distribute verbatim copies of this <br />manual provided the copyright notice and this permission notice are <br />preserved on all copies. <br /> <br />&nbsp;&nbsp; Permission is granted to copy and distribute modified versions of <br />this manual under the conditions for verbatim copying, provided also <br />that the entire resulting derived work is distributed under the terms <br />of a permission notice identical to this one. <br /> <br />&nbsp;&nbsp; Permission is granted to copy and distribute translations of this <br />manual into another language, under the above conditions for modified <br />versions. <br /> <br />使用GDB: <br />&nbsp;&nbsp; 本文描述GDB,GNU的原代码调试器。(这是4.12版1994年一月，GDB版本4。16) <br />* 目录： <br />* 摘要：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GDB的摘要 <br />* 实例：&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; 一个使用实例 <br />* 入门：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 进入和退出GDB <br />* 命令：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GDB 的命令 <br />* 运行：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在GDB下运行程序 <br />* 停止：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 暂停和继续执行 <br />* 栈：&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; 检查堆栈 <br />* 原文件：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 检查原文件 <br />* 数据：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 检查数据 <br />* 语言：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用不同的语言来使用GDB <br />* 符号：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 检查符号表 <br />* 更改：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 更改执行 <br />* GDB的文件&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 文件 <br />* 对象&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; 指定调试对象 <br />* 控制GDB&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 控制 <br />* 执行序列：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 执行一序列命令 <br />* Emacs:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使GDB和Emacs一起工作 <br />* GDB的bug: <br />* 命令行编辑：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 行编辑 <br />* 使用历史记录交互： <br />* 格式化文档：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如何格式化和打印GDB文档 <br />* 安装GDB ： <br /> <br />* 索引： <br /> <br />GDB简介： <br />************** <br /> <br />&nbsp;&nbsp; 调试器(比如象GDB)能让你观察另一个程序在执行时的内部活动，或程序出错时 <br />发生了什么。 <br />&nbsp;&nbsp; GDB主要能为你做四件事(包括为了完成这些事而附加的功能)，帮助你找出程序 <br />中的错误。 <br />&nbsp;&nbsp; * 运行你的程序，设置所有的能影响程序运行的东西。 <br /> <br />&nbsp;&nbsp; * 保证你的程序在指定的条件下停止。 <br /> <br />&nbsp;&nbsp; * 当你程序停止时，让你检查发生了什么。 <br /> <br />&nbsp;&nbsp; * 改变你的程序。那样你可以试着修正某个bug引起的问题，然后继续查找另一 <br />&nbsp;&nbsp;&nbsp;&nbsp; 个bug. <br /> <br />&nbsp;&nbsp; 你可以用GDB来调试C和C++写的程序。(参考 *C 和C++) <br /> <br />&nbsp;&nbsp; 部分支持Modula-2和chill，但现在还没有这方面的文档。 <br /> <br />&nbsp;&nbsp; 调试Pascal程序时，有一些功能还不能使用。 <br /> <br />&nbsp; GDB还可以用来调试FORTRAN程序，尽管现在还不支持表达式的输入，输出变量， <br />或类FORTRAN的词法。 <br />* GDB是&quot;free software&quot;，大家都可以免费拷贝。也可以为GDB增加新的功能，不 <br />过可要遵守GNU的许可协议幺。反正我认为GNU还是比较不错的：-) <br />就这句话： <br />&nbsp;&nbsp; Fundamentally, the General Public License is a license which says <br />that you have these freedoms and that you cannot take these freedoms <br />away from anyone else. <br />GDB的作者： <br />&nbsp;&nbsp; Richard Stallman是GDB的始作俑者,另外还有许多别的GNU的成员。许多人 <br />为此作出了贡献。(都是老外不提也罢，但愿他们不要来找我麻烦：-))<pre><pre>这里是GDB的一个例子： <br />        原文中是使用一个叫m4的程序。但很遗憾我找不到这个程序的原代码， <br />所以没有办法来按照原文来说明。不过反正是个例子，我就拿一个操作系统的 <br />进程调度原码来说明把，原代码我会附在后面。 <br />        首先这个程序叫os.c是一个模拟进程调度的原程序(也许是个老古董了：-))。 <br />先说明一下如何取得包括原代码符号的可执行代码。大家有心的话可以去看一下gcc的 <br />man文件(在shell下打man gcc)。gcc -g &lt;原文件.c&gt; -o &lt;要生成的文件名&gt; <br />-g 的意思是生成带原代码调试符号的可执行文件。 <br />-o 的意思是指定可执行文件名。 <br />(gcc 的命令行参数有一大堆，有兴趣可以自己去看看。) <br />反正在linux下把os.c用以上方法编译连接以后就产生了可供gdb使用的可执行文件。 <br />我用gcc -g os.c -o os，产生的可执行文档叫os. <br />然后打gdb os,就可进入gdb，屏幕提示： <br />     GDB is free software and you are welcome to distribute copies <br />      of it under certain conditions; type &quot;show copying&quot; to see <br />      the conditions. <br />     There is absolutely no warranty for GDB; type &quot;show warranty&quot; <br />      for details. <br /> <br />     GDB 4.16, Copyright 1995 Free Software Foundation, Inc... <br /> (gdb) <br />  (gdb)是提示符，在这提示符下可以输入命令，直到退出。(退出命令是q/Q) <br />为了尽量和原文档说明的命令相符，即使在本例子中没用的命令我也将演示。 <br />首先我们可以设置gdb的屏幕大小。键入： <br /> (gdb)set width 70 <br />就是把标准屏幕设为70列。 <br />  然后让我们来设置断点。设置方法很简单:break或简单打b后面加行号或函数名 <br />比如我们可以在main 函数上设断点： <br /> (gdb)break main <br />或(gdb)b main <br /> 系统提示：Breakpoint 1 at 0x8049552: file os.c, line 455. <br /> 然后我们可以运行这个程序，当程序运行到main函数时程序就会停止返回到gdb的 <br />提示符下。运行的命令是run或r(gdb中有不少alias,可以看一下help,在gdb下打help) <br />run 后面可以跟参数，就是为程序指定命令行参数。 <br />比如r abcd，则程序就会abcd以作为参数。(这里要说明的是可以用set args来指定参 <br />数)。打入r或run后，程序就开始运行直到进入main的入口停止，显示： <br />Starting program: &lt;路径&gt;/os <br /> <br />Breakpoint 1, main () at os.c:455 <br />455            Initial(); <br />这里455 Initial();是将要执行的命令或函数。 <br />gdb提供两种方式：1.单步进入,step into就是跟踪到函数内啦。命令是step或s <br />                 2.单步，next，就是简单的单步，不会进入函数。命令是next或n <br />这两个命令还有别的用法以后再说。 <br />我们用n命令，键入: <br />(gdb)n <br />Success forking process# 1 ,pid is 31474 <br /> <br />Success forking process# 2 ,pid is 31475 <br /> <br />Success forking process# 3 ,pid is 31476 <br /> <br />Success forking process# 4 ,pid is 31477 <br /> <br />Success forking process# 5 ,pid is 31478 <br /> <br />Success forking process# 6 ,pid is 31479 <br /> <br />                Dispatching Algorithm : FIFO <br />******************************************************************************** <br /> <br />            PCB#        PID     Priority        PC      State <br />            1           31474      24            0      WAITING <br />            2           31475      19            0      WAITING <br />            3           31476      16            0      WAITING <br />            4           31477      23            0      WAITING <br />            5           31478      22            0      WAITING <br />            6           31479      20            0      WAITING <br /> <br />****************************************************************************** <br /> <br />CPU  :  NO process running <br />IO :  No process <br />Waiting CPU!!!  31474   31475   31476   31477   31478   31479 <br />Waiting  IO    NONE <br />456            State=WAITING; <br />最后的一行就是下一句要执行的命令。我们现在在另一个函数上加断点。注意我们 <br />可以用l/list命令来显示原代码。这里我们键入 <br />(gdb)l <br />451     main() <br />452     { <br />453             int message; <br />454 <br />455            Initial(); <br />456            State=WAITING; <br />457            printf(&quot;Use Control-C to halt \n&quot;); <br />458            signal(SIGALRM,AlarmMessage); <br />459            signal(SIGINT,InteruptMessage); <br />460            signal(SIGUSR2,IoMessage); <br />(gdb) l <br />461            alarm(TimeSlot); <br />462            for(;;) <br />463             { <br />464             message=GetMessage(); <br />465                   switch(message) <br />466                     { <br />467                             case INTERRUPT :        printf(&quot;Use Control-C t; <br /> <br />468                                                     break; <br />469                             case CHILD_IO:          WaitingIo(); <br />470                                                     break; <br />显示了原代码，现在在AlarmMessage上加断点。 <br />(gdb) b AlarmMessage <br />Breakpoint 2 at 0x8048ee3: file os.c, line 259. <br />(gdb) <br />然后我们继续运行程序。 <br />(gdb)c <br />c或continue命令让我们继续被中断的程序。 显示： <br />Continuing. <br />Use Control-C to halt <br /> <br />Breakpoint 2, AlarmMessage () at os.c:259 <br />259             ClearSignal(); <br />注意我们下一句语句就是ClearSignal(); <br />我们用s/step跟踪进入这个函数看看它是干什么的。 <br />(gdb) s <br />ClearSignal () at os.c:227 <br />227             signal(SIGINT,SIG_IGN); <br />用l命令列出原代码： <br />(gdb) l <br />222     } <br />223 <br />224 <br />225     void ClearSignal()    /* Clear other signals */ <br />226     { <br />227             signal(SIGINT,SIG_IGN); <br />228             signal(SIGALRM,SIG_IGN); <br />229             signal(SIGUSR2,SIG_IGN); <br />230     } <br />231 <br />(gdb) <br />我们可以用s命令继续跟踪。现在让我们来试试bt或backtrace命令。这个命令可以 <br />显示栈中的内容。 <br />(gdb) bt <br />#0  ClearSignal () at os.c:227 <br />#1  0x8048ee8 in AlarmMessage () at os.c:259 <br />#2  0xbffffaec in ?? () <br />#3  0x80486ae in ___crt_dummy__ () <br />(gdb) <br />大家一定能看懂显示的意思。栈顶是AlarmMessage，接下来的函数没有名字--就是 <br />没有原代码符号。这显示了函数调用的嵌套。 <br />好了，我们跟踪了半天还没有检查过变量的值呢。检查表达式的值的命令是p或print <br />格式是p &lt;表达式&gt; <br />444444让我们来找一个变量来看看。：-) <br />(gdb)l 1 <br />还记得l的作用吗？l或list显示原代码符号，l或list加&lt;行号&gt;就显示从&lt;行号&gt;开始的 <br />原代码。好了找到一个让我们来看看WaitingQueue的内容 <br />(gdb) p WaitingQueue <br />$1 = {1, 2, 3, 4, 5, 6, 0} <br />(gdb) <br />WaitingQueue是一个数组，gdb还支持结构的显示， <br />(gdb) p Pcb <br />$2 = {{Pid = 0, State = 0, Prior = 0, pc = 0}, {Pid = 31474, State = 2, <br />    Prior = 24, pc = 0}, {Pid = 31475, State = 2, Prior = 19, pc = 0}, { <br />    Pid = 31476, State = 2, Prior = 16, pc = 0}, {Pid = 31477, State = 2, <br />    Prior = 23, pc = 0}, {Pid = 31478, State = 2, Prior = 22, pc = 0}, { <br />    Pid = 31479, State = 2, Prior = 20, pc = 0}} <br />(gdb) <br />这里可以对照原程序看看。 <br />原文档里是一个调试过程，不过我想这里我已经把gdb的常用功能介绍了一遍，基本上 <br />可以用来调试程序了。：-) </pre><pre>&nbsp;</pre><pre><pre>运行GDB(一些详细的说明)： <br /> <br />  前面已经提到过如何运行GDB了，现在让我们来看一些更有趣的东西。你可以在运行 <br />GDB时通过许多命令行参数指定大量的参数和选项，通过这个你可以在一开始就设置好 <br />程序运行的环境。 <br />  这里将要描述的命令行参数覆盖了大多数的情况，事实上在一定环境下有的并没有 <br />什么大用处。最通常的命令就是使用一个参数： <br /> $gdb &lt;可执行文档名&gt; <br />你还可以同时为你的执行文件指定一个core文件： <br /> $gdb &lt;可执行文件名&gt; core <br />你也可以为你要执行的文件指定一个进程号： <br /> $gdb &lt;可执行文件名&gt; &lt;进程号&gt; 如：&amp;gdb os 1234将使gdb与进程1234相联系(attach) <br />除非你还有一个文件叫1234的。gdb首先检查一个core文件。 <br />如果你是使用一个远程终端进行远程调试的话，那如果你的终端不支持的话，你将无法 <br />使用第二个参数甚至没有core dump。如果你觉得开头的提示信息比较碍眼的话，你可以 <br />用gdb -silent。你还可以用命令行参数更加详细的控制GDB的行为。 <br />打入gdb -help或-h 可以得到这方面的提示。所有的参数都被按照排列的顺序传给gdb <br />除非你用了-x参数。 <br />  当gdb开始运行时，它把任何一个不带选项前缀的参数都当作为一个可执行文件或core <br />文件(或进程号)。就象在前面加了-se或-c选项。gdb把第一个前面没有选项说明的参数 <br />看作前面加了-se 选项，而第二个(如果有的话)看作是跟着-c选项后面的。 <br />  许多选项有缩写，用gdb -h可以看到。在gdb中你也可以任意的把选项名掐头去尾，只 <br />要保证gdb能判断唯一的一个参数就行。 <br />在这里我们说明一些最常用的参数选项 <br />-symbols &lt;文件名&gt;(-s &lt;文件名&gt;)------从&lt;文件名&gt;中读去符号。 <br />-exec &lt;文件名&gt;(-e &lt;文件名&gt;)----在合适的时候执行&lt;文件名&gt;来做用正确的数据与core <br /> dump的作比较。 <br />-se &lt;文件名&gt;------从&lt;文件名&gt;中读取符号并把它作为可执行文件。 <br />-core &lt;文件名&gt;(-c &lt;文件名&gt;)--指定&lt;文件名&gt;为一个core dump 文件。 <br />-c &lt;数字&gt;----连接到进程号为&lt;数字&gt;，与attach命令相似。 <br />-command &lt;文件名&gt; <br />-x &lt;文件名&gt;-----执行gdb命令，在&lt;文件名&gt;指定的文件中存放着一序列的gdb命令，就 <br />象一个批处理。 <br />-directory(-d) &lt;路径&gt;---指定路径。把&lt;路径&gt;加入到搜索原文件的路径中。 <br />-m <br />-mapped---- <br />   注意这个命令不是在所有的系统上都能用。如果你可以通过mmap系统调用来获得内存 <br />映象文件，你可以用这个命令来使gdb把你当前文件里的符号写入一个文件中，这个文件 <br />将存放在你的当前路径中。如果你调试的程序叫/temp/fred那么map文件就叫 <br />./fred.syms这样当你以后再调试这个程序时，gdb会认识到这个文件的存在，从而从这 <br />个文件中读取符号，而不是从可执行文件中读取。.syms与主机有关不能共享。 <br />-r <br />-readnow---马上从符号文件中读取整个符号表，而不是使用缺省的。缺省的符号表是 <br />调入一部分符号，当需要时再读入一部分。这会使开始进入gdb慢一些，但可以加快以后 <br />的调试速度。 <br /> <br /> -m和-r一般在一起使用来建立.syms文件 <br /> <br /> <br />接下来再谈谈模式的设置(请听下回分解 :-)) <br />附：在gdb文档里使用的调试例子我找到了在minix下有这个程序,叫m4有兴趣的 <br />可以自己去看看模式的选择 <br />-------------- <br />现在我们来聊聊gdb运行模式的选择。我们可以用许多模式来运行gdb，例如在&quot;批模式&quot; <br />或&quot;安静模式&quot;。这些模式都是在gdb运行时在命令行作为选项指定的。 <br />`-nx' <br />`-n' <br />     不执行任何初始化文件中的命令。(一般初始化文件叫做`.gdbinit').一般情况下在 <br />这些文件中的命令会在所有的命令行参数都被传给gdb后执行。 <br /> <br />`-quiet' <br />`-q' <br />     &quot;安静模式&quot;。不输出介绍和版权信息。这些信息在&quot;批模式&quot;中也被跳过。 <br /> <br />`-batch' <br />     &quot;批模式&quot;。在&quot;批模式&quot;下运行。当在命令文件中的所有命令都被成功的执行后 <br />     gdb返回状态&quot;0&quot;，如果在执行过程中出错，gdb返回一个非零值。 <br />     &quot;批模式&quot;在把gdb作为一个过滤器运行时很有用。比如在一台远程计算机上下载且 <br />     执行一个程序。信息&quot; Program exited normally&quot;(一般是当运行的程序正常结束 <br />     时出现)不会在这种模式中出现。 <br />`-cd DIRECTORY' <br />     把DIRECTORY作为gdb的工作目录，而非当前目录(一般gdb缺省把当前目录作为工作目 <br />     录)。 <br />`-fullname' <br />`-f' <br />     GNU Emacs 设置这个选项，当我们在Emacs下，把gdb作为它的一个子进程来运行时， <br />     Emacs告诉gdb按标准输出完整的文件名和行号，一个可视的栈内容。这个格式跟在 <br />     文件名的后面。行号和字符重新按列排，Emacs-to-GDB界面使用\032字符作为一个 <br />     显示一页原文件的信号。 <br />`-b BPS' <br />     为远程调试设置波特率。 <br /> <br />`-tty DEVICE' <br />     使用DEVICE来作为你程序的标准输入输出。 </pre><pre><pre>退出gdb <br />============ <br /> <br />`quit' <br />     使用'quit'命令来退出gdb,或打一个文件结束符(通常是' CTROL-D')。如果 <br />     你没有使用表达式，gdb会正常退出，否则它会把表达式的至作为error code <br />     返回。 <br /> <br />     一个中断(通常是'CTROL-c)不会导致从gdb中退出，而是结束任何一个gdb的命 <br />     令，返回gdb的命令输入模式。一般在任何时候使用'CTROL-C'是安全的，因为 <br />     gdb会截获它，只有当安全时，中断才会起作用。 <br />     如果你正在用gdb控制一个被连接的进程或设备，你可以用'detach'命令来释放 <br />     它。 <br /> <br />Shell命令 <br />============== <br />    当你偶尔要运行一些shell命令时，你不必退出调试过程，也不需要挂起它；你 <br />    可以使用'shell'命令。 <br /> <br />`shell COMMAND STRING' <br />     调用标准shell来执行'COMMAND STRING'.环境变量'SHELL'决定了那个shell被 <br />     运行。否则gdb使用'/bin/sh'. <br />     'make'工具经常在开发环境中使用，所以你可以不用'shell'命令而直接打'make' <br /> <br />`make MAKE-ARGS' <br />     用指定的命令行变量来运行'make'程序，这等于使用'shell make MAKE-ARGS' <br />GDB 命令 <br />************ <br />   我们可以把一个gdb命令缩写成开头几个字母，如果这没有二意性你可以直接回车来 <br />   运行。你还可以使用TAB键让gdb给你完成接下来的键入，或向你显示可选择的命令， <br />   如果有不止一个选择的话。 <br /> <br />Command语法 <br />============== <br /> <br />   一个gdb命令是一个单行的输入。长度没有限制。它一个命令开头，后面可以跟参量。 <br />   比如命令'step'接受一个参量表示单步执行多少步。你也可以不用参量。有的命令 <br />   不接受任何参量。 <br /> <br />   gdb命令只要没有二意性的话就可以被缩写。另外一些缩写作为一个命令列出。在某些 <br />   情况下二意也是允许的。比如's'是指定'step'的缩写，但还有命令'start'。你可以把 <br />   这些缩写作为'help'命令的参量来测试它们。 <br />   空行(直接回车)表示重复上一个命令。但有些命令不能重复比如象'run'，就不会以这 <br />   种方式重复，另外一些当不小心重复会产生严重后果的命令也不能用这种方法重复。 <br />   'list'和'x'命令当你简单的打回车时，会建立新的变量，而不是简单的重复上一个命 <br />   令。这样你可以方便的浏览原代码和内存。 <br />   gdb还有一种解释RET的方法：分割长输出。这种方法就和'more'命令相似。由于这时经 <br />   常会不小心多打回车，gdb将禁止重复当一个命令产生很长的输出时。 <br />   任何用'#'开头一直到行尾的命令行被看作是注释。主要在命令文件中使用。 </pre><pre><pre>输入命令的技巧 <br />================== <br />   前面已经提到过TAB键的使用。使用TAB键能让你方便的得到所要的命令。比如 <br />在gdb中： <br />   (gdb)info bre &lt;TAB&gt;(键入info bre,后按TAB键) <br />   gdb能为你完成剩下的输入。它还能萎蔫提供选择的可能性。如果有两个以上可 <br />能的话，第一次按&lt;TAB&gt;键，gdb会响铃提示，第二次则显示可能的选择。同样gdb <br />也可以为一些子命令提供快速的访问。用法与上相同。 <br />  上例中显示 <br />   (gdb)info breakepoints <br />   你也可以直接打回车，gdb就将你输入的作为命令的可能的缩写。来判断执行。 <br />如果你打入的缩写不足以判断，那么gdb会显示一个列表，列出可能的命令。同样的 <br />情况对于命令的参数。在显示完后gdb把你的输入拷贝到当前行以便让你继续输入。 <br />   如果你只想看看命令的列表或选项，你可以在命令行下打M-?(就是按着ESC键 <br />同时按SHIFT和？键)。你可以直接在命令行下打试试。 <br />  (gdb)&lt;M-?&gt; <br />   gdb会响铃并显示所有的命令。不过这种方式好象在远程调试是不行。当有的命令 <br />使用一个字符串时，你可以用&quot; ' &quot;将其括起来。这种方法在调试C++程序时特别有用。 <br />因为C++支持函数的重载。当你要在某个有重载函数上设断点时，不得不给出函数参数 <br />以区分不同的重载函数。这时你就应该把整个函数用&quot; ' &quot;括起来。比如,你要在一个 <br />叫name的函数上设断点，而这个函数被重载了(name(int)和name(float))。你将不得 <br />不给出参变量以区分不同的函数。使用'name(int)'和'name(float)'。这里有个技巧， <br />你可以在函数名前加一个&quot; ' &quot;符号。然后打M-?. </pre><pre><pre>得到帮助 <br />============ <br />   你可以使用help命令来得到gdb的在线帮助。 <br /> <br />`help' <br />`h' <br />      你可以使用help或h后面不加任何参数来得到一个gdb命令类的列表。 <br /> <br />          (gdb) help <br />          List of classes of commands: <br /> <br />          running -- Running the program <br />          stack -- Examining the stack <br />          data -- Examining data <br />          breakpoints -- Making program stop at certain points <br />          files -- Specifying and examining files <br />          status -- Status inquiries <br />          support -- Support facilities <br />          user-defined -- User-defined commands <br />          aliases -- Aliases of other commands <br />          obscure -- Obscure features <br /> <br />          Type &quot;help&quot; followed by a class name for a list of <br />          commands in that class. <br />          Type &quot;help&quot; followed by command name for full <br />          documentation. <br />          Command name abbreviations are allowed if unambiguous. <br />          (gdb) <br /> <br />`help CLASS' <br />     使用上面列出的help class作为help或h的参量，你可以得到单一的命令列表。 <br />     例如显示一个'status'类的列表。 <br /> <br />          (gdb) help status <br />          Status inquiries. <br /> <br />          List of commands: <br /> <br />          show -- Generic command for showing things set <br />           with &quot;set&quot; <br />          info -- Generic command for printing status <br /> <br />          Type &quot;help&quot; followed by command name for full <br />          documentation. <br />          Command name abbreviations are allowed if unambiguous. <br />          (gdb) <br /> <br />`help COMMAND' <br />     详细列出单个命令的资料。 <br /> <br />`complete ARGS' <br />     列出所有以ARGS开头的命令。例如： <br /> <br />          complete i <br /> <br />     results in: <br /> <br />          info <br />          inspect <br />          ignore <br /> <br />     This is intended for use by GNU Emacs. <br /> <br />   除了使用'help'你还可以使用gdb的命令'info'和'show'来查询你程序的 <br />状态，每个命令可以查询一系列的状态。这些命令以恰当的方式显示所有的 <br />子命令。 <br /> <br />`info' <br />     此命令(可以缩写为'i')用来显示你程序的状态。比如，你可以使用info <br />args 列出你程序所接受的命令行参数。使用info registers列出寄存器的状态。 <br />或用info breakpoint列出在程序中设的断点。要获得详细的关于info的信息打 <br />help info. <br />`set' <br />     这个命令用来为你的程序设置一个运行环境(使用一个表达式)。比如你 <br />可以用set prompt $来把gdb的提示符设为$. <br /> <br />`show' <br />     与'info'相反，'show'命令用来显示gdb自身的状态。你使用'set'命令来 <br />可以改变绝大多数由'show'显示的信息。比如使用show radix命令来显示基数。 <br />用不带任何参变量的'set'命令你可以显示所有你可以设置的变量的值。 <br />有三个变量是不可以用'set'命令来设置的。 <br />`show version' <br />     显示gdb的版本号。如果你发现gdb有bug的话你应该在bug-reports里加 <br />入gdb的版本号。 <br /> <br />`show copying' <br />显示版权信息。 <br /> <br />`show warranty' <br />显示担保信息。 <br />在gdb下运行你的程序 <br />************************** <br />   当你在gdb下运行程序时，你必须先为gdb准备好带有调试信息的可执行文档。 <br />还可以在gdb中为你的程序设置参变量，重定向你程序的输入/输出，设置环境变 <br />量，调试一个已经执行的程序或kill掉一个子进程。 <br />   这里许多内容在早先的例子中都已经用到过，可以参见gdb(二)。 <br />目录： <br /> <br />* 编译::                        为调试编译带调试信息的代码 <br />* 运行::                        运行你的程序 <br />* 参变量::                      为你的程序设置参变量 <br />* 运行环境::                    为你的程序设置运行时环境 <br />* 设置工作目录::                在gdb中设置程序的工作目录。 <br />* 输入/输出::                   设定你程序的输入和输出 <br />* 连接::                        调试一个已经运行的程序 <br />* 结束子进程::                  Kill子进程 <br />* 进程信息::                    附加的进程信息 <br />* 线程::                        调试带多线程的程序 <br />* 多进程::                   调试带多进程的程序 <br />为调试准备带调试信息的代码 <br />=========================== <br />   为了高效的调试一个程序，你需要使用编译器来产生附带调试信息的可执行代码 <br />这些调试信息存储在目标文件中；描述了变量数据类型和函数声明，在原文件代码行 <br />和执行代码之间建立联系。 <br />   为产生调试信息，当你使用编译器时指定'-g'选项，就可以为你的程序产生带有 <br />调试信息的可执行代码。 <br />   有些c编译器不支持'-g'选项和'-O'选项，那你就有麻烦了，或者有别的方法产生 <br />带调试信息的可执行代码，要不就没办法了。 <br />   gcc，GNU的c语言编译器支持'-g'和'-O'选项。这样你就可以产生带调试信息的且 <br />优化过的可执行代码. <br />   当你使用gdb来调试一个使用'-g','-O'选项产生的程序时，千万记住编译器为了优 <br />化你的程序重新安排了你的程序。不要为运行次序与你原来设想的不同，最简单的例子 <br />就是当你定义了一个变量但从未使用过它时，gdb中是看不到这个变量的--因为它已经 <br />被优化掉了。 <br />   所以有时你不要使用'-O'选项，如果当你不用优化时产生的程序是正确的，而优化 <br />过后变的不正确了，那么这是编译器的bug你可以向开发者提供bug-reports(包括出错 <br />的例子)。 <br />   早期的GUN C语言编译器允许'-gg'选项，也用来产生调试信息，gdb不再支持这种格 <br />式的调试信息，如果你的编译器支持'-gg'选项，请不要使用它。 <br /><br />开运行你的程序 <br />===================== <br /> <br />`run' <br />`r' <br />     使用'run'命令在gdb下启动你的程序。你必须先指定你程序的名字(用gdb的命令行 <br />参数)或使用'file'命令，来指定文件名。如果你在一个支持多进程的环境下运行你的程 <br />序'run'命令创建一个子进程然后加载你的程序。如果环境不支持进程，则gdb直接调到 <br />程序的第一条命令。 <br />   一些父进程设置的参量可以决定程序的运行。gdb提供了指定参量的途径，但你必须 <br />在程序执行前设置好他们。你也可以在运行过程中改变它们，但每次改变只有在下一次 <br />运行中才会体现出来。这些参量可以分为四类： <br />---参数 <br />     你可以在使用'run'命令时设置，如果shell支持的话，你还可以使用通配符，或 <br />变量代换。在UNIX系统中你可以使用'shell环境变量'来控制shell。 <br />---环境： <br />     你的程序一般直接从gdb那里继承环境变量。但是你可以使用'set environment' <br />命令来设置专门的环境变量。 <br />---工作目录 <br />     你的程序还同时从gdb那里继承了工作目录,你可以使用'cd'命令在gdb中改变工作 <br />目录。 <br />---标准输入/输出 <br />     你的程序一般使用与gdb所用的相似的设备来输入/输出。不过你可以为你的程序的 <br />输入/输出进行重定向。使用'run'或'tty'命令来设置于gdb所用不同的设备。 <br />*注意：当你使用输入/输出重定向时，你将不能使用无名管道来把你所调试的程序的输出 <br />传给另一个程序。这样gdb会认为调试程序出错。 <br />   当你发出'run'命令后，你的程序就开始运行。 <br />   如果你的符号文件的时间与gdb上一次读入的不同，gdb会废弃原来的符号表并重新读 <br />入。当前的断点不变。 </pre><pre><pre>程序环境 <br />========================== <br />   &quot;环境&quot;包括了一系列的环境变量和它们的值。环境变量一般记录了一些常用的信息， <br />比如你的用户名，主目录，你的终端型号和你的运行程序的搜索路径。一般你可以在shell <br />下设置环境变量，然后这些变量被所有你所运行的程序所共享。在调试中，可以设置恰当 <br />的环境变量而不用退出gdb. <br /> <br />`path DIRECTORY' <br />     在'PATH'环境变量前加入新的内容('PATH'提供了搜索执行文件的路径)。对于gdb和 <br />你的程序来说你也许要设置一些专门的路径。使用':'或空格来分隔。如果DIRECTORY已经 <br />在路径中了，这个操作将会把它移到前面。 <br />     你可以使用串'$cmd'来代表当前路径，如果你用'.'的话，它代表你使用'path'命令 <br />时的路径,gdb将在把DIRECTORY加入搜索路径前用'.'代替当前路径 <br /> <br />`show paths' <br />     显示当前路径变量的设置情况。 <br /> <br />`show environment [VARNAME]' <br />     显示某个环境变量的值。如果你不指明变量名，则gdb会显示所有的变量名和它们的 <br />内容。environment可以被缩写成'env' <br /> <br />`set environment VARNAME [=] VALUE' <br />     设置某个环境变量的值。不过只对你所调试的程序有效。对gdb本身是不起作用的。 <br />值可以是任何串。如果未指定值，则该变量值将被设为NULL. <br />看一个例子： <br />          set env USER = foo <br />     告诉一个linux程序，当它下一次运行是用户名将是'foo' <br /> <br />`unset environment VARNAME' <br />     删除某环境变量。 <br /> <br />   注意：gdb使用'shell'环境变量所指定的shell来运行你的程序。 <br /> <br /> <br />工作路径 <br />================================ <br />   当你每次用'run'命令来运行你的程序时，你的程序将继承gdb的 <br />当前工作目录。而gdb的工作目录是从它的父进程继承而来的(一般是 <br />shell)。但你可以自己使用'cd'命令指定工作目录。 <br />   gdb的工作目录就是它去寻找某些文件或信息的途径。 <br />`cd DIRECTORY' <br />     把gdb的工作目录设为DIRECTORY <br />`pwd' <br />     打印输出当前目录。 <br />你程序的输入/输出 <br />=============================== <br />   缺省时，你的程序的输入/输出和gdb的输入/输出使用同一个终端。 <br />gdb在它自己和你的程序之间切换来和你交互，但这会引起混乱。 <br />`info terminal' <br />     显示你当前所使用的终端的类型信息。 <br />     你可以把你程序的输入/输出重定向。 <br />例如： <br />     run &gt; outfile <br />运行你的程序并把你程序的标准输出写入文件outfile中。 <br />   另一个为你程序指定输入/输出的方法是使用'tty'命令，这个命令 <br />接受一个文件名作为参量把这个文件作为以后使用'run'命令的缺省命 <br />令文件。它还重新为子进程设置控制终端。 <br />例如： <br />     tty /dev/ttyb <br />指定以后用'run'命令启动的进程使用终端'/dev/ttyb'作为程序的输入 <br />/输出，而且把这个终端设为你进程的控制终端。 <br />   一个清楚的使用'run'命令的重定向将重新设置'tty'所设置的内容 <br />，但不影响控制终端。   当你使用'tty'命令或在'run'命令中对输入 <br />/输出进行重定向时，只有你当前调试的程序的输入/输出被改变了， <br />并不会影响到别的程序。 <br />调试一个已经运行的程序： <br />==================================== <br /> <br />`attach PROCESS-ID' <br />     这个命令把一个已经运行的进程(在gdb外启动)连接入gdb,以便 <br />调试。PROCESS-ID是进程号。(UNIX中使用'ps'或'jobs -l'来查看进程) <br />     'attach'一般不重复。(当你打了一个以上的回车时) <br />   当然要使用'attach'命令的话，你的操作系统环境必须支持进程。 <br />另外你还要有向此进程发信号的权力。 <br />   当使用'attach'命令时，你应该先使用'file'命令来指定进程所 <br />联系的程序源代码和符号表。   当gdb接到'attach'命令后第一件 <br />事就是停止进程的运行，你可以使用所有gdb的命令来调试一个&quot;连接&quot; <br />的进程，就象你用'run'命令在gdb中启动它一样。如果你要进程继续运 <br />行，使用'continue'或'c'命令就行了。 <br />`detach' <br />   当你结束调试后可以使用此命令来断开进程和gdb的连接。(解除gdb <br />对它的控制)在这个命令执行后进程将继续执行。 <br />   如果你在用'attach'连接一个进程后退出了gdb，或使用'run'命令执 <br />行了另一个进程，这个被'attach'的进程将被kill掉。但缺省时，gdb会 <br />要求你确认你是否要退出或执行一个新的进程。 </pre><pre><pre>结束子进程 <br />========================= <br />`kill' <br />     Kill命令结束你程序在gdb下开的子进程 <br />     这个命令当你想要调试(检查)一个core dump文件时更有用。gdb在调试过程中 <br />会忽略所有的core dump。 <br />   在一些操作系统上，一个程序当你在上面加了断点以后就不能离开gdb独立运行。 <br />你可以用kill命令来解决这个问题。 <br />   'kill'命令当你想重新编译和连接你的程序时也很有用。因为有些系统不允许修改 <br />正在执行的可执行程序。这样当你再一次使用'run'命令时gdb会知道你的程序已经被改 <br />变了，那么gdb会重新load新的符号。(而且尽量保持你当前的断点设置。 <br />附加的进程信息 <br />============================== <br />   一些操作系统提供了一个设备目录叫做'/proc'的，供检查进程映象。如果gdb被在这 <br />样的操作系统下运行，你可以使用命令'info proc'来查询进程的信息。('info proc'命 <br />令只在支持'procfs'的SVR4系统上有用。 <br />`info proc' <br />     显示进程的概要信息。 <br />`info proc mappings' <br />     报告你进程所能访问的地址范围。 <br />`info proc times' <br />     你进程和子进程的开始时间，用户时间(user CPU time),和系统CPU时间。 <br />`info proc id' <br />     报告有关进程id的信息。 <br />`info proc status' <br />     报告你进程的一般状态信息。如果进程停止了。这个报告还包括停止的原因和收到的 <br />信号。 <br />`info proc all' <br />     显示上面这些命令返回的所有信息。 <br />对多线程程序的调试 <br />======================================== <br />   一些操作系统中，一个单独的程序可以有一个以上的线程在运行。线程和进程精确的定?nbsp;<br />?nbsp;<br /> <br />?nbsp;<br />?nbsp;<br />有自己的寄存器，运行时堆栈或许还会有私有内存。 <br />   gdb提供了以下供调试多线程的进程的功能： <br />   * 自动通告新线程。 <br />   * 'thread THREADNO'，一个用来在线程之间切换的命令。 <br />   * 'info threads'，一个用来查询现存线程的命令。 <br />   * 'thread apply [THREADNO] [ALL] ARGS',一个用来向线程提供命令的命令。 <br />   * 线程有关的断点设置。 <br />   注意：这些特性不是在所有gdb版本都能使用，归根结底要看操作系统是否支持。 <br />   如果你的gdb不支持这些命令，会显示出错信息： <br />          (gdb) info threads <br />          (gdb) thread 1 <br />          Thread ID 1 not known.  Use the &quot;info threads&quot; command to <br />          see the IDs of currently known threads. <br />   gdb的线程级调试功能允许你观察你程序运行中所有的线程，但无论什么时候 <br />gdb控制，总有一个&quot;当前&quot;线程。调试命令对&quot;当前&quot;进程起作用。 <br />   一旦gdb发现了你程序中的一个新的线程，它会自动显示有关此线程的系统信 <br />息。比如： <br />     [New process 35 thread 27] <br />不过格式和操作系统有关。 <br />   为了调试的目的，gdb自己设置线程号。 <br />`info threads' <br />     显示进程中所有的线程的概要信息。gdb按顺序显示： <br />       1.线程号(gdb设置) <br />       2.目标系统的线程标识。 <br />       3.此线程的当前堆栈。 <br />       一前面打'*'的线程表示是当前线程。 <br />     例如： <br />     (gdb) info threads <br />       3 process 35 thread 27  0x34e5 in sigpause () <br />       2 process 35 thread 23  0x34e5 in sigpause () <br />     * 1 process 35 thread 13  main (argc=1, argv=0x7ffffff8) <br />         at threadtest.c:68 <br />`thread THREADNO' <br />     把线程号为THREADNO的线程设为当前线程。命令行参数THREADNO是gdb内定的 <br />线程号。你可以用'info threads'命令来查看gdb内设置的线程号。gdb显示该线程 <br />的系统定义的标识号和线程对应的堆栈。比如： <br /> <br />          (gdb) thread 2 <br />          [Switching to process 35 thread 23] <br />          0x34e5 in sigpause () <br />     &quot;Switching后的内容取决于你的操作系统对线程标识的定义。 <br /> <br />`thread apply [THREADNO] [ALL]  ARGS' <br />     此命令让你对一个以上的线程发出相同的命令&quot;ARGS&quot;,[THREADNO]的含义同上。 <br />如果你要向你进程中的所有的线程发出命令使用[ALL]选项。 <br />   无论gdb何时中断了你的程序(因为一个断点或是一个信号)，它自动选择信号或 <br />断点发生的线程为当前线程。gdb将用一个格式为'[Switching to SYSTAG]'的消息 <br />来向你报告。 <br />   *参见：运行和停止多线程程序。 <br />   *参见：设置观察点 <br /> <br />调试多进程的程序 <br />========================================== <br />   gdb对调试使用'fork'系统调用产生新进程的程序没有很多支持。当一个程序开始 <br />一个新进程时，gdb将继续对父进程进行调试，子进程将不受影响的运行。如果你在子 <br />进程可能会执行到的地方设了断点，那么子进程将收到'SIGTRAP'信号，如果子进程没 <br />有对这个信号进行处理的话那么缺省的处理就是使子进程终止。 <br />   然而，如果你要一定要调试子进程的话，这儿有一个不是很麻烦的折衷的办法。在 <br />子进程被运行起来的开头几句语句前加上一个'sleep'命令。这在调试过程中并不会引 <br />起程序中很大的麻烦(不过你要自己注意例外的情况幺：-))。然后再使用'ps'命令列出 <br />新开的子进程号，最后使用'attach'命令。这样就没有问题了。 <br />  关于这一段，本人觉得实际使用上并不全是这样。我在调试程中就试过，好象不一定 <br />能起作用，要看gdb的版本和你所使用的操作系统了。 <br />停止和继续 <br />*********************** <br />   调试器的基本功能就是让你能够在程序运行时在终止之前在某些条件下停止下来，然 <br />后再继续运行，这样的话你就可以检查当你的程序出错时你的程序究竟做了些什么。 <br />   在gdb内部，你的程序会由于各种原因而暂时停止，比如一个信号，一个断点，或是 <br />由于你用了'step'命令。在程序停止的时候你就可以检查和改变变量的值，设置或去掉 <br />断点，然后继续你程序的运行。一般当程序停下来时gdb都会显示一些有关程序状态的信 <br />息。比如象程序停止的原因，堆栈等等。如果你要了解更详细的信息，你可以使用'info <br />program'命令。另外，在任何时候你输入这条命令，gdb都会显示当前程序运行的状态信 <br />息。 <br /> <br />`info program' <br />     显示有关你程序状态的信息：你的程序是在运行还是停止，是什么进程，为什么停 <br />止。 <br /> <br />断点，观察点和异常 <br />======================================== <br />   断点的作用是当你程序运行到断点时，无论它在做什么都会被停止下来。对于每个断点 <br />你都可以设置一些更高级的信息以决定断点在什么时候起作用。你可以使用'break'命令 <br />来在你的程序中设置断点，在前面的例子中我们已经提到过一些这个命令的使用方法了。 <br />你可以在行上，函数上，甚至在确切的地址上设置断点。在含有异常处理的语言(比如象 <br />c++)中，你还可以在异常发生的地方设置断点。 <br />   在SunOS 4.x,SVR4和Alpha OSF/1的设置中，你还可以在共享库中设置断点。 <br />   观察点是一种特殊的断点。它们在你程序中某个表达式的值发生变化时起作用。你必 <br />须使用另外一些命令来设置观察点。除了这个特性以外，你可以象对普通断点一样对观察 <br />点进行操作--使用和普通断点操作一样的命令来对观察点使能，使不能，删除。 <br />   你可以安排当你程序被中断时显示的程序变量。 <br />   当你在程序中设置断点或观察点时gdb为每个断点或观察点赋一个数值.在许多对断点 <br />操作的命令中都要使用这个数值。 </pre><pre>设置断点 <br />============= <br />   使用'break'或简写成'b'来设置断点。gdb使用环境变量$bpnum来记录你最新设置的 <br />断点。 <br />   你有不少方法来设置断点。 <br /> <br /> <br />`break FUNCTION' <br />     此命令用来在某个函数上设置断点。当你使用允许函数重载的语言比如C++时，有可 <br />能同时在几个重载的函数上设置了断点。 <br /> <br />`break +OFFSET' <br />`break -OFFSET' <br />     在当前程序运行到的前几行或后几行设置断点。OFFSET为行号。 <br /> <br />`break LINENUM' <br />     在行号为LINENUM的行上设置断点。程序在运行到此行之前停止。 <br /> <br />`break FILENAME:LINENUM' <br />     在文件名为FILENAME的原文件的第LINENUM行设置断点。 <br /> <br />`break FILENAME:FUNCTION' <br />     在文件名为FILENAME的原文件的名为FUNCTION的函数上设置断点。 <br />当你的多个文件中可能含有相同的函数名时必须给出文件名。 <br /> <br />`break *ADDRESS' <br />     在地址ADDRESS上设置断点，这个命令允许你在没有调试信息的程 <br />序中设置断点。 <br />`break' <br />     当'break'命令不包含任何参数时，'break'命令在当前执行到的程 <br />序运行栈中的下一条指令上设置一个断点。除了栈底以外，这个命令使 <br />程序在一旦从当前函数返回时停止。相似的命令是'finish'，但'finish' <br />并不设置断点。这一点在循环语句中很有用。 <br />     gdb在恢复执行时，至少执行一条指令。 <br /> <br />`break ... if COND' <br />     这个命令设置一个条件断点，条件由COND指定；在gdb每次执行到此 <br />断点时COND都被计算当COND的值为非零时，程序在断点处停止。这意味着 <br />COND的值为真时程序停止。...可以为下面所说的一些参量。 <br /> <br />`tbreak ARGS' <br />     设置断点为只有效一次。ARGS的使用同'break'中的参量的使用。 <br /> <br />`hbreak ARGS' <br />     设置一个由硬件支持的断点。ARGS同'break'命令，设置方法也和 <br />'break'相同。但这种断点需要由硬件支持，所以不是所有的系统上这个 <br />命令都有效。这个命令的主要目的是用于对EPROM/ROM程序的调试。因为 <br />这条命令可以在不改变代码的情况下设置断点。这可以同SPARCLite DSU <br />一起使用。当程序访问某些变量和代码时，DSU将设置&quot;陷井&quot;。注意： <br />你只能一次使用一个断点，在新设置断点时，先删除原断点。 <br />`thbreak ARGS' <br />     设置只有一次作用的硬件支持断点。ARGS用法同'hbreak'命令。这个命令 <br />和'tbreak'命令相似，它所设置的断点只起一次作用，然后就被自动的删除。这 <br />个命令所设置的断点需要有硬件支持。 <br /> <br />`rbreak REGEX' <br />     在所有满足表达式REGEX的函数上设置断点。这个命令在所有相匹配的函数 <br />上设置无条件断点，当这个命令完成时显示所有被设置的断点信息。这个命令设 <br />置的断点和'break'命令设置的没有什么不同。这样你可以象操作一般的断点一 <br />样对这个命令设置的断点进行删除，使能，使不能等操作。当调试C++程序时这 <br />个命令在重载函数上设置断点时非常有用。 <br /> <br />`info breakpoints [N]' <br />`info break [N]' <br />`info watchpoints [N]' <br />     显示所有的断点和观察点的设置表，有下列一些列 <br /> <br />    *Breakpoint Numbers*----断点号 <br />    *Type*----断点类型(断点或是观察点) <br />    *Disposition*---显示断点的状态。 <br /> <br />    *Enabled or Disabled*---使能或不使能。'y'表示使能，'n'表示不使能。 <br /> <br />    *Address*----地址，断点在你程序中的地址(内存地址) <br />    *What*---地址，断点在你程序中的行号。 <br />     如果断点是条件断点，此命令还显示断点所需要的条件。 <br />     带参数N的'info break'命令只显示由N指定的断点的信息。 <br />     此命令还显示断点的运行信息(被执行过几次)，这个功能在使用'ignore' <br />命令时很有用。你可以'ignore'一个断点许多次。使用这个命令可以查看断点 <br />被执行了多少次。这样可以更快的找到错误。 <br />    gdb允许你在一个地方设置多个断点。但设置相同的断点无疑是弱智的。不过 <br />你可以使用条件断点，这样就非常有用。 <br />   gdb有时会自动在你的程序中加入断点。这主要是gdb自己的需要。比如为了正 <br />确的处理C语言中的'longjmp'。这些内部断点都是负值，以'-1'开始。'info <br />breakpoints'不会显示它们。 <br />   不过你可以使用命令'maint info breakpoints'来查看这些断点。 <br /> <br />`maint info breakpoints' <br />     使用格式和'info breakpoints'相同，显示所有的断点，无论是你设置的还是 <br />gdb自动设置的。 <br />     以下列的含义： <br /> <br />    `breakpoint' <br />          断点，普通断点。 <br />    `watchpoint' <br />          普通观察点。 <br /> <br />    `longjmp' <br />          内部断点，用于处理'longjmp'调用。 <br /> <br />    `longjmp resume' <br />          内部断点，设置在'longjmp'调用的目标上。 <br /> <br />    `until' <br />          'until'命令所使用的内部断点。 <br /> <br />    `finish' <br />          'finish'命令所使用的内部断点。 <br />设置观察点 <br />============== <br />   你可以使用观察点来停止一个程序，当某个表达式的值改变时，观察点会将程序 <br />停止。而不需要先指定在某个地方设置一个断点。 <br />   由于观察点的这个特性，使观察点的使用时开销比较大，但在捕捉错误时非常有 <br />用。特别是你不知道你的程序什么地方出了问题时。 <br /> <br />`watch EXPR' <br />     这个命令使用EXPR作为表达式设置一个观察点。GDB将把表达式加入到程序中 <br />并监视程序的运行，当表达式的值被改变时GDB就使程序停止。这个也可以被用在 <br />SPARClite DSU提供的新的自陷工具中。当程序存取某个地址或某条指令时(这个地 <br />址在调试寄存器中指定),DSU将产生自陷。对于数据地址DSU支持'watch'命令,然而 <br />硬件断点寄存器只能存储两个断点地址，而且断点的类型必须相同。就是两个 <br />'rwatch'型断点，或是两个'awatch'型断点。 <br /> <br />`rwatch EXPR' <br />     设置一个观察点，当EXPR被程序读时，程序被暂停。 <br /> <br />`awatch EXPR' <br />     设置一个观察点,当EXPR被读出然后被写入时程序被暂停。这个命令和'awatch' <br />命令合用。 <br /> <br />`info watchpoints' <br />     显示所设置的观察点的列表，和'info break'命令相似。 <br />     *注意：*在多线程的程序中，观察点的作用很有限，GDB只能观察在一个线程中 <br />的表达式的值如果你确信表达式只被当前线程所存取，那么使用观察点才有效。GDB <br />不能注意一个非当前线程对表达式值的改变。 <br /> <br />断点和异常 <br />============== <br />   在一些语言中比如象GNU C++，实现了异常处理。你可以使用GDB来检查异常发生的 <br />原因。而且GDB还可以列出在某个点上异常处理的所有过程。 <br /> <br />`catch EXCEPTIONS' <br />     你可以使用这个命令来在一个被激活的异常处理句柄中设置断点。EXCEPTIONS是 <br />一个你要抓住的异常。 <br />     你一样可以使用'info catch'命令来列出活跃的异常处理句柄。 <br />     现在GDB中对于异常处理由以下情况不能处理。 <br />   * 如果你使用一个交互的函数，当函数运行结束时，GDB将象普通情况一样把控制返 <br />回给你。如果在调用中发生了异常，这个函数将继续运行直到遇到一个断点，一个信号 <br />或是退出运行。 <br />   * 你不能手工产生一个异常( 即异常只能由程序运行中产生 ) <br />   * 你不能手工设置一个异常处理句柄。 <br />   有时'catch'命令不一定是调试异常处理的最好的方法。如果你需要知道异常产生的 <br />确切位置，最好在异常处理句柄被调用以前设置一个断点，这样你可以检查栈的内容。 <br />如果你在一个异常处理句柄上设置断点，那么你就不容易知道异常发生的位置和原因。 <br />   要仅仅只在异常处理句柄被唤醒之前设置断点，你必须了解一些语言的实现细节。 <br />比如在GNU C++中异常被一个叫'__raise_exception'的库函数所调用。这个函数的原 <br />型是： <br /> <br />         /* ADDR is where the exception identifier is stored. <br />            ID is the exception identifier.  */ <br />         void __raise_exception (void **ADDR, void *ID); <br />要使GDB在栈展开之前抓住所有的句柄，你可以在函数'__raise_exception'上设置断点。 <br />   对于一个条件断点，由于它取决于ID的值，你可以在你程序中设置断点，当某个特 <br />别的异常被唤醒。当有一系列异常被唤醒时，你可以使用多重条件断点来停止你的程序。</pre><pre><pre>断点条件 <br />=========== <br />   最简单的断点就是当你的程序每次执行到的时候就简单将程序挂起。你也可以为断点 <br />设置&quot;条件&quot;。条件只是你所使用的编程语言的一个布尔表达式，带有条件表达式的断点 <br />在每次执行时判断计算表达式的值，当表达式值为真时才挂起程序。 <br />   这是使用&quot;断言&quot;的一中形式，在这种形式中你只有在断言为真时才挂起程序。如果 <br />在C语言中你要使断言为假时挂起程序则使用：&quot;!表达式&quot;。 <br />   条件表达式对观察点也同样有效，但你并不需要它，因为观察点本身就计算一个表达式?nbsp;<br />?nbsp;<br />但它也许会简单一些。比如只在一个变量名上设置观察点然后设置一个条件来测试新的赋 <br />值。 <br />  断点条件可能有副作用(side effects)会影响程序的运行。这一点有时也是很有用的 <br />比如来激活一个显示程序完成情况的的函数，或使用你自己的打印函数来格式化特殊的 <br />数据结构。当在同一位置没有另一个断点设置时，结果是可预见的。(在gdb中如果在同一 <br />个地方使用了一个断点和一个条件断点则普通断点可能先被激活。)在条件断点的应用上 <br />有很多技巧。 <br />   断点条件可以在设置断点的同时被设置。使用'if'命令作为'break'命令的参数。断点 <br />条件也可以在任何时候使用'condition'命令来设置。'watch'命令不能以'if'作为参数 <br /> <br />所以使用'condition'命令是在观察点上设置条件的唯一方法。 <br /> <br />`condition BNUM EXPRESSION' <br />     把'EXPRESSIN'作为断点条件。断点用'BNUM'来指定。在你为BNUM号断点设置了条件 <br />后，只有在条件为真时程序才被暂停。当你使用'condition'命令GDB马上同步的检查 <br />'EXPRESSION'的值判断表达式中的符号在断点处是否有效，但GDB并不真正计算表达式 <br />的值。 <br /> <br />`condition BNUM' <br />     删除在'BNUM'号断点处的条件。使之成为一个普通断点。 <br />   一个条件断点的特殊例子是时一个程序在执行了某句语句若干次后停止。由于这 <br />个功能非常常用，你可以使用一个命令来直接设置它那就是'ignore count'。每个 <br />断点都有'ignore count'，缺省是零。如果'ignore count'是正的那么你的程序在 <br />运行过断点处'count'次后被暂停。 <br /> <br />`ignore BNUM COUNT' <br />     设置第BNUM号断点的'ignore count'为'COUNT'。 <br />     如果要让断点在下次执行到时就暂停程序，那么把'COUNT'设为0. <br />     当你使用'continue'命令来继续你程序的执行时，你可以直接把'ignore count' <br />作为'continue'的参数使用。你只要直接在'continue'命令后直接跟要&quot;ignore&quot;的 <br />次数就行。 <br />     如果一个断点同时有一个ignore count和一个条件时，条件不被检查。只有当 <br />'ignore count'为零时GDB才开始检查条件的真假。 <br />     另外你可以用'condition'命令来获得与用&lsquo;ignore count'同样效果的断点。用法 <br />是用类似于'$foo--&lt;=0'的参量作为'condition'命令的参数(使用一个不停减量的变量 <br />作为条件表达式的成员)。 <br /> 断点命令列表 <br />================== <br />   你可以为任一个断点或观察点指定一系列命令，当你程序执行到断点时，GDB自动执行 <br />这些命令。例如：你可以打印一些表达式的值，或使能其他的断点。 <br /> <br />`commands [BNUM]' <br />`... COMMAND-LIST ...' <br />`end' <br />     为断点号为BNUM的断点设置一个命令列表。这些命令在'...COMMAND-LIST...'中列 <br />出使用'end'命令来表示列表的结束。 <br />    要删除断点上设置的命令序列，你只需在'command'命令后直接跟'end'命令就可以 <br />了。 <br />    当不指定BNUM时，GDB缺省为最近遇到的断点或是观察点设置命令列表。 <br />    使用回车来表示重复使用命令的特性在'...command list...'中不能使用。 <br />    你可以使用命令列表中的命令来再次使你的程序进入运行状态。简单的在命令列表 <br />中使用'continue'命令，或'step'命令。 <br />    在使程序恢复执行的命令后的命令都被忽略。这是因为一旦你的程序重新运行就可 <br />能遇到新的命令列表，那么就应该执行新的命令。防止了二义。 <br />    如果你在命令列表中使用了'silent'命令，那么你程序在断点处停止的信息将不被 <br />显示。这对于用一个断点然后显示一些信息，接着再继续执行很有用。但'silent'命令 <br />只有在命令列表的开头有效。 <br />    命令'echo','output'和'printf'允许你精确的控制显示信息，这些命令在&quot;silent&quot; <br />断点中很有用。 <br />   例如：这个例子演示了使用断点命令列表来打印'x'的值. <br /> <br />     break foo if x&gt;0 <br />     commands <br />     silent <br />     printf &quot;x is %d\n&quot;,x <br />     cont <br />     end <br />   断点命令列表的一个应用是在遇到一个buf之后改正数据然后继续调试的过程。 <br />使用命令来修改含有错误值的变量，然后使用'continue'命令继续程序的运行。 <br />  使用'silent'命令屏蔽输出： <br /> <br />     break 403 <br />     commands <br />     silent <br />     set x = y + 4 <br />     cont <br />     end <br />断点菜单 <br />============== <br />   一些编程语言(比如象C++)允许一个函数名被多次使用(重载)，以方便应用的使用。 <br />当一个函数名被重载时，'break FUNCITON'命令向GDB提供的信息不够GDB了解你要设置 <br />断点的确切位置。如果你了解到这个问题，你可以使用'break FUNCITONS(TYPES)'命令 <br />来指定断点的确切位置。否则GDB会提供一个函数的选择的菜单供你选择。使用提示符 <br />'&gt;'来等待你的输入。开始的两个选择一般是'[0] cancel'和'[1] all'输入1则在所有 <br />同名函数上加入断点。输入0则退出选择。 <br />   下例为企图在重载的函数符号'String::after'上设置断点。 <br />     (gdb) b String::after <br />     [0] cancel <br />     [1] all <br />     [2] file:String.cc; line number:867 <br />     [3] file:String.cc; line number:860 <br />     [4] file:String.cc; line number:875 <br />     [5] file:String.cc; line number:853 <br />     [6] file:String.cc; line number:846 <br />     [7] file:String.cc; line number:735 <br />     &gt; 2 4 6 <br />     Breakpoint 1 at 0xb26c: file String.cc, line 867. <br />     Breakpoint 2 at 0xb344: file String.cc, line 875. <br />     Breakpoint 3 at 0xafcc: file String.cc, line 846. <br />     Multiple breakpoints were set. <br />     Use the &quot;delete&quot; command to delete unwanted <br />      breakpoints. <br />     (gdb) </pre></pre></pre></pre></pre></pre></pre></pre></pre></span>&nbsp;
          <br/>
          <span style="color:red;">
            <a href="http://draculaw.javaeye.com/blog/160296#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 31 Jul 2007 14:28:00 +0800</pubDate>
        <link>http://draculaw.javaeye.com/blog/160296</link>
        <guid>http://draculaw.javaeye.com/blog/160296</guid>
      </item>
      <item>
        <title>Overlapped I/O 與 I/O Completion Port Model</title>
        <author>DraculaW</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://draculaw.javaeye.com">DraculaW</a>&nbsp;
          链接：<a href="http://draculaw.javaeye.com/blog/160297" style="color:red;">http://draculaw.javaeye.com/blog/160297</a>&nbsp;
          发表时间: 2007年07月30日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Overlapped I/O是Windows對I/O操作的一個封裝<br /> 他可以用在文件,socket等很多地方<br /> 用來從I/O設備讀寫數據<br /> 一般來說 用BSD socket的話 就需要為讀寫專門起一個線程 由自己處理讀寫的操作。這樣不能說不好，但是如果有人幫處理過了可以減輕負擔，那就太好不過了<br /> 于是MS就推出了Overlapped I/O這個操作模式<br /> 它的本質也是操作系統起一個線程來處理讀寫。但是省去了自己對線程的控制。<br /> 其主要思想就是把讀寫操作設置為overlapped模式 然后等待操作完成的event。 如果event被觸發則進入下一步的操作。<br /> <br /> 嗯 好像說的有點混亂........<br /> <br /> 簡而言之 言而簡之 Overlapped I/O模式就是一種異步通訊的模式<br /> <br /> 異步通訊和同步通訊不同，同步通訊時當執行完一個操作後進行下一個操作 而異步通訊則執行一個的同時執行下一個。<br /><br />&nbsp;這個也是一種I/O操作的模式 <br /> 具體很像<a href="http://hi.baidu.com/draculaw/blog/item/dde8513b8a239de814cecb69.html">Overlapped  I/O</a>的 只是更復雜一些<br /> 有說法說 IO Complection Port是windows提供的最復雜的內核對象了<br /> <br /> 这个模式用来编