<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9975629</id><updated>2012-01-09T23:21:44.454+08:00</updated><category term='Visual Studio'/><category term='Programming Language'/><category term='MySQL'/><category term='gdb'/><category term='Version Control'/><category term='音樂歌曲'/><category term='RVO'/><category term='C/C++'/><category term='FPU'/><category term='C++0x'/><category term='Tutorial'/><category term='Windows'/><category term='SCREAM Lab'/><category term='Search'/><category term='OO'/><category term='Movie'/><category term='floating point'/><category term='PHP'/><category term='研發替代役'/><category term='test'/><category term='騰雲駕霧程式競賽'/><category term='翻譯'/><category term='Interrupt Handling'/><category term='VMware'/><category term='雜七雜八'/><category term='Qt'/><category term='Debugging'/><category term='gcc'/><category term='Boost.Program_options'/><category term='Apache'/><category term='g++'/><category term='Book'/><category term='Boost'/><category term='Concepts'/><category term='Ohana'/><category term='Blog'/><category term='Optimization'/><category term='Server Host'/><title type='text'>Paramecium</title><subtitle type='html'>希望有一天，人們會指著我說：NK，我真是搞不懂你啊～</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default?start-index=101&amp;max-results=100'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>149</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9975629.post-5365884201510066703</id><published>2011-04-17T12:31:00.001+08:00</published><updated>2011-04-27T10:42:21.172+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VMware'/><title type='text'>VMware 64-bit Guest OS Support</title><content type='html'>&lt;p&gt;去年聖誕節買的 x201 ，下單前還特別注意 CPU 是否支援 Virtualization ，直到上個月拿來跑 64 bit guest OS 時，才發現 Windows 會進入開機、當機的無窮迴圈。後來才發現一些小眉角，尤其是在筆電上：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;不是 64-bit OS 就可以直接支援 64-bit guest OS ，必須 CPU 有支援 &lt;a href="http://en.wikipedia.org/wiki/X86_virtualization" target="_blank"&gt;VT&lt;/a&gt; 才行。 &lt;/li&gt;    &lt;li&gt;大多數筆電的 VT 預設值都是關閉，必須進入 BIOS 啟動。 &lt;/li&gt;    &lt;li&gt;在 BIOS 中，若有 Hardware data execution 之類的 H/W security 功能最好也關閉。 &lt;/li&gt;    &lt;li&gt;部分筆電，像是 Lenovo x201 ，要讓上述設定生效，還必須將電池、電源移除，按下電源開關，進行放電， BIOS 的改動才會生效。 &lt;/li&gt; &lt;/ol&gt;  &lt;h1&gt;測試方式&lt;/h1&gt;  &lt;p&gt;如果不確定 CPU 是否支援 VT ，可以到 Intel/AMS 的網站查詢，像是 &lt;a href="http://ark.intel.com/Default.aspx" target="_blank"&gt;Intel Processor Spec. Finder&lt;/a&gt; 或 &lt;a href="http://products.amd.com/en-us/desktopcpuresult.aspx" target="_blank"&gt;AMD Desktop Processor&lt;/a&gt;。&lt;/p&gt;  &lt;h2&gt;Processor Check for 64-Bit Compatibility&lt;/h2&gt;  &lt;p&gt;[感謝 &lt;a href="http://www.blogger.com/profile/07230890664149450670" target="_blank"&gt;Allen Lai&lt;/a&gt; 提醒]&lt;/p&gt;  &lt;p&gt;VMware 提供了一個快速的檢測工具——Processor Check for 64-Bit Compatibility，雖然已經很久沒更新了，不過它的結果明確易懂，像是下圖就說明：&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/TbeCiDBjB0I/AAAAAAAAA8k/39-Osqbjbpw/s1600-h/Processor%20Check%20for%2064-Bit%20Compatibility%5B4%5D.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top: 0px; border-right: 0px; padding-top: 0px" title="Processor Check for 64-Bit Compatibility" border="0" alt="Processor Check for 64-Bit Compatibility" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/TbeCiz8mZ2I/AAAAAAAAA8o/DaXFxa2Kmzo/Processor%20Check%20for%2064-Bit%20Compatibility_thumb%5B2%5D.jpg?imgmax=800" width="481" height="178" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;不過根據&lt;a href="http://downloads.vmware.com/pdf/processor_check.pdf" target="_blank"&gt;說明文件&lt;/a&gt;，它目前只支援特定的 processors ，而且還有幾項是 experimental support：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;AMD™ Athlon™ 64, revision D or later&lt;/li&gt;    &lt;li&gt;AMD Opteron™, revision E or later&lt;/li&gt;    &lt;li&gt;AMD Turion™ 64, revision E or later&lt;/li&gt;    &lt;li&gt;AMD Sempron™, 64-bit-capable revision D or later (experimental support)&lt;/li&gt;    &lt;li&gt;Intel™ EM64T VT-capable processors (experimental support)&lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;VMware CPU Identification Utility&lt;/h2&gt;  &lt;p&gt;或是利用 VMware 的 &lt;a href="http://www.vmware.com/download/shared_utilities.html" target="_blank"&gt;CPU Identification Utility&lt;/a&gt; ，這是個 可用來開機的 ISO 檔，使用時只需要掛載進 VMware 即可 。&lt;/p&gt;  &lt;p&gt;未啟動 VT 時的輸出：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/Tbaw8vMbzSI/AAAAAAAAA8c/3TDWNhL9uy4/s1600-h/CPU%20Identification%20Utility%20%28Before%29%5B3%5D.png"&gt;&lt;img style="border-right-width: 0px; margin: 0px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="CPU Identification Utility (Before)" border="0" alt="CPU Identification Utility (Before)" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/Tbaw9Jo4spI/AAAAAAAAA8g/PzUjQWLQN18/CPU%20Identification%20Utility%20%28Before%29_thumb%5B1%5D.png?imgmax=800" width="644" height="360" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;啟動 VT 後：&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/TaptGheVVXI/AAAAAAAAA8U/xe_BVaYizpI/s1600-h/CPU%20Identification%20Utility%5B6%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="CPU Identification Utility" border="0" alt="CPU Identification Utility" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/TaptHDCg24I/AAAAAAAAA8Y/Kf6M4yzkLmg/CPU%20Identification%20Utility_thumb%5B4%5D.png?imgmax=800" width="644" height="360" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;上面的圖是 x201 開啟 VT 後的結果，&lt;strike&gt;根據說明文件和實驗，似乎紅框裡有一個是 Yes ，就可以支援 64-bit guest OS 。&lt;/strike&gt;根據 &lt;a href="http://www.blogger.com/profile/07230890664149450670" target="_blank"&gt;Allen Lai&lt;/a&gt; 的測試，即使 64-bit LongMode 顯示 YES ，也並非能支援 64-bit guest OS。所以目前還沒有比較好的解讀方式 … 大概只是方便你把結果丟到 support 或 community 去發問 … &lt;/p&gt;  &lt;p&gt;最後要注意的是，當 CPU features 設定改變後，都可能讓已經建立好的 snapshots 出問題。&lt;/p&gt;  &lt;h1&gt;Reference&lt;/h1&gt;  &lt;ol&gt;   &lt;li&gt;VMware Shared Utility: &lt;a title="http://www.vmware.com/download/shared_utilities.html" href="http://www.vmware.com/download/shared_utilities.html"&gt;http://www.vmware.com/download/shared_utilities.html&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Ensuring your hardware is functioning correctly: &lt;a title="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&amp;amp;cmd=displayKC&amp;amp;externalId=1003690" href="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&amp;amp;cmd=displayKC&amp;amp;externalId=1003690"&gt;http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&amp;amp;cmd=displayKC&amp;amp;externalId=1003690&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Ensuring Virtualization Technology is enabled on your VMware host: &lt;a title="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&amp;amp;cmd=displayKC&amp;amp;externalId=1003944" href="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&amp;amp;cmd=displayKC&amp;amp;externalId=1003944"&gt;http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&amp;amp;cmd=displayKC&amp;amp;externalId=1003944&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Hardware and firmware requirements for 64-bit Guest Operating Systems: &lt;a title="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&amp;amp;cmd=displayKC&amp;amp;externalId=1003945" href="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&amp;amp;cmd=displayKC&amp;amp;externalId=1003945"&gt;http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&amp;amp;cmd=displayKC&amp;amp;externalId=1003945&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Intel Processor Spec. Finder: &lt;a title="http://ark.intel.com/Default.aspx" href="http://ark.intel.com/Default.aspx"&gt;http://ark.intel.com/Default.aspx&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;AMD Desktop Processor: &lt;a title="http://products.amd.com/en-us/desktopcpuresult.aspx" href="http://products.amd.com/en-us/desktopcpuresult.aspx"&gt;http://products.amd.com/en-us/desktopcpuresult.aspx&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;      &lt;h1&gt;更新&lt;/h1&gt;  &lt;p&gt;2011/4/26: 補上 x201 未啟動 VT 的 VMware CPU Identification 結果截圖。&lt;/p&gt;  &lt;p&gt;2011/4/27: 補充 &lt;a href="http://www.blogger.com/profile/07230890664149450670" target="_blank"&gt;Allen Lai&lt;/a&gt; 的連結和測試工具 Processor Check for 64-Bit Compatibility 。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-5365884201510066703?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/5365884201510066703/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=5365884201510066703' title='9 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5365884201510066703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5365884201510066703'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2011/04/vmware-64-bit-guest-os-support.html' title='VMware 64-bit Guest OS Support'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_2ZMoTkLFVu8/TbeCiz8mZ2I/AAAAAAAAA8o/DaXFxa2Kmzo/s72-c/Processor%20Check%20for%2064-Bit%20Compatibility_thumb%5B2%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-6139783788809617027</id><published>2010-08-29T16:27:00.001+08:00</published><updated>2010-08-29T16:42:54.825+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='g++'/><category scheme='http://www.blogger.com/atom/ns#' term='gcc'/><category scheme='http://www.blogger.com/atom/ns#' term='FPU'/><category scheme='http://www.blogger.com/atom/ns#' term='gdb'/><category scheme='http://www.blogger.com/atom/ns#' term='Debugging'/><category scheme='http://www.blogger.com/atom/ns#' term='floating point'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimization'/><title type='text'>Re: GCC Bug</title><content type='html'>&lt;p&gt;原文：&lt;a href="http://screamlab-ncku-2008.blogspot.com/2010/08/gcc-bug.html" target="_blank"&gt;GCC Bug&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;哈，這次老師給我的作業可是難題，有好一陣子沒有碰觸 gdb ，更何況這次還要跟 FPU 打交道，下面是我的測試程式，和原文只有小部份差異，但重點部份是一樣的：&lt;/p&gt;  &lt;pre class="brush: cpp; highlight: [11,19];"&gt;#include &amp;lt;cstdio&amp;gt;
using namespace std;

double f(double z)
{
    return z;
}

void foo(double fraction)
{
    double z = fraction * 20.0;
    int t1 = z;
    int t2 = f(z);
    printf(&amp;quot;t1=%d, t2=%d\n&amp;quot;, t1, t2);
}

int main()
{
    foo(6.0/20.0);
    return 0;
}&lt;/pre&gt;

&lt;h1&gt;問題&lt;/h1&gt;

&lt;p&gt;輸出： &lt;/p&gt;

&lt;p&gt;6, 6 &lt;/p&gt;

&lt;p&gt;是我們預期的結果。但在某些情況下卻會產生&lt;/p&gt;

&lt;p&gt;5, 6 &lt;/p&gt;

&lt;p&gt;這樣的輸出。但若是在 compile 時加上 -ffloat-store 則又能得到正確的結果。根據 gcc optimization options 的說明：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Do not store floating point variables in registers, and inhibit other options that might change whether a floating point value is taken from a register or memory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;我們懷疑是從 register 讀出時發生意想不到的進位，導致結果有所出入。&lt;/p&gt;

&lt;h1&gt;實驗&lt;/h1&gt;

&lt;p&gt;一開始在嘗試 reproduce 時就遇上問題，在和 aaa 討論後才發現，我們使用的 gcc 版本和 compile options 都不盡相同。最後確定了發生問題的環境：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;cygwin + gcc 3.4.4 &lt;/li&gt;

  &lt;li&gt;gcc –O text.c &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;下面是我嘗試過的平台和結果：&lt;/p&gt;

&lt;div align="center"&gt;
  &lt;table border="1" cellspacing="0" cellpadding="2" width="401" align="center"&gt;&lt;tbody&gt;
      &lt;tr&gt;
        &lt;td valign="top" width="133"&gt;&amp;#160;&lt;/td&gt;

        &lt;td valign="top" width="133"&gt;-O&lt;/td&gt;

        &lt;td valign="top" width="133"&gt;-O3&lt;/td&gt;
      &lt;/tr&gt;

      &lt;tr&gt;
        &lt;td valign="top" width="133"&gt;gcc 4.4.1&lt;/td&gt;

        &lt;td valign="top" width="133"&gt;No&lt;/td&gt;

        &lt;td valign="top" width="133"&gt;No&lt;/td&gt;
      &lt;/tr&gt;

      &lt;tr&gt;
        &lt;td valign="top" width="133"&gt;gcc 3.4.4 (cygwin)&lt;/td&gt;

        &lt;td valign="top" width="133"&gt;&lt;font color="#ff0000"&gt;Yes&lt;/font&gt;&lt;/td&gt;

        &lt;td valign="top" width="133"&gt;No&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;有趣的開始！&lt;/p&gt;

&lt;h2&gt;O3 版本&lt;/h2&gt;

&lt;pre class="brush: cpp"&gt;g++ -Wall -O3 -S -masm=intel main.cpp&lt;/pre&gt;

&lt;p&gt;這個版本是最好理解的， compiler 已經最佳化到：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;不呼叫 foo()、f()，直接以常數取代。（沒記錯，這算是 compiler const folding 和 const propagation 的範疇） &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;看一下 assembly 就很清楚：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [14, 15];"&gt;LC2:
	.ascii &amp;quot;t1=%d, t2=%d\12\0&amp;quot;
	.align 4
...
_main:
    push   ebp
    mov    eax, 16
    mov    ebp, esp
    sub    esp, 24
    and    esp, -16
    call   __alloca
    call   ___main
    mov    DWORD PTR [esp], OFFSET FLAT:LC2 ; 看一眼 LC2 ，一個取址動作 :)
    mov    edx, 6
    mov    eax, 6
    mov    DWORD PTR [esp+8], edx
    mov    DWORD PTR [esp+4], eax
    call   _printf
    leave
    xor    eax, eax
    ret&lt;/pre&gt;

&lt;h2&gt;O 版本&lt;/h2&gt;

&lt;pre class="brush: cpp"&gt;g++ -Wall -O -S -masm=intel main.cpp&lt;/pre&gt;

&lt;p&gt;O 版本就沒那麼聰明，而是真正的去呼叫 foo() ：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [9,10, 11];"&gt;_main:
    push   ebp
    mov    ebp, esp
    sub    esp, 8
    and    esp, -16
    mov    eax, 16
    call   __alloca
    call   ___main
    fld    QWORD PTR LC4
    fstp   QWORD PTR [esp]
    call   __Z3food
    mov    eax, 0
    leave
    ret&lt;/pre&gt;

&lt;p&gt;而且可以發現，LC4 是 foo() 的參數：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [9];"&gt;LC4:
	.long	858993459
	.long	1070805811
	.text
	.align 2


0.3 的 IEEE 754 Double precision (64 bits) 表示式：
0 01111111101 00110011001100110011  110011001100110011001100110011
                        1070805811                       858993459&lt;/pre&gt;

&lt;p&gt;嗯嗯，O 版本先做了簡單的運算展開。不過在進入 foo() 的 floating point 計算前，得先對 x87 FPU 有簡單的概念 ：&lt;/p&gt;

&lt;p align="center"&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/THoZ64zgzRI/AAAAAAAAA4I/Oy3oVOaBY4Q/s1600-h/image3.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/THoZ7XMH1FI/AAAAAAAAA4M/e94NXzfH_mY/image_thumb1.png?imgmax=800" width="644" height="444" /&gt;&lt;/a&gt;節錄自： &lt;a href="http://www.intel.com/Assets/PDF/manual/253665.pdf" target="_blank"&gt;Intel® 64 and IA-32 Architectures Software Developer’s Manual ─ Volume 1: Basic Architecture&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;x87 上用來儲存資料的 registers 被組織成一塊 stack 的，並且搭配了 control, status 等 registers 可供控制、查詢之用。 Stack 以下圖的方式運做：&lt;/p&gt;

&lt;p align="center"&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/THoZ8FKZGsI/AAAAAAAAA4Q/lhQ8cojntfU/s1600-h/image10.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/THoZ9NCQJYI/AAAAAAAAA4U/saXA5RHuvkg/image_thumb4.png?imgmax=800" width="644" height="271" /&gt;&lt;/a&gt;節錄自： &lt;a href="http://www.intel.com/Assets/PDF/manual/253665.pdf" target="_blank"&gt;Intel® 64 and IA-32 Architectures Software Developer’s Manual ─ Volume 1: Basic Architecture&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Stack 的 top 又稱為 ST(0)，是許多 FPU 指令的隱藏 operand 之一，像是待會在 foo() 看見的 fld、fstp、fmul 指令都會 implicitly 操作 ST(0) 。&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [7, 13, 15, 25];"&gt;__Z3food:
    push    ebp
    mov     ebp, esp
    push    ebx
    sub     esp, 20
    fld     DWORD PTR LC1
    fmul    QWORD PTR [ebp+8]
    fnstcw  WORD PTR [ebp-6]
    movzx   eax, WORD PTR [ebp-6]
    or      ax, 3072
    mov     WORD PTR [ebp-8], ax
    fldcw   WORD PTR [ebp-8]
    fist    DWORD PTR [ebp-12]      ; store integer
    fldcw   WORD PTR [ebp-6]
    mov     ebx, DWORD PTR [ebp-12]
    fstp    QWORD PTR [esp]
    call    __Z1fd
    fnstcw  WORD PTR [ebp-6]
    movzx   eax, WORD PTR [ebp-6]
    or      ax, 3072
    mov     WORD PTR [ebp-8], ax
    fldcw   WORD PTR [ebp-8]
    fistp   DWORD PTR [esp+8]
    fldcw   WORD PTR [ebp-6]
    mov     DWORD PTR [esp+4], ebx
    mov     DWORD PTR [esp], OFFSET FLAT:LC2
    call    _printf
    add     esp, 20
    pop     ebx
    pop     ebp
    ret&lt;/pre&gt;

&lt;p&gt;這邊使用倒推法，來找到 t1 及其在 assembly 的表示，尋著上頭的 highlight 部份，可以發現：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;printf 從 ebx 拿到 t1 的值，也就是 ebx 、 &lt;/li&gt;

  &lt;li&gt;ebx 由 ebp-12 得到、 &lt;/li&gt;

  &lt;li&gt;ebp-12 則是 fist 的結果，也就是 FPU 的 ST(0)、 &lt;/li&gt;

  &lt;li&gt;往上回溯，只有 L6 處有個 fld ，因此，ST(0) 指的是 fmul 的結果、 &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;反推的過程也符合程式的邏輯，所以下一步就是用 debugger 去追蹤：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [1, 4, 12, 18];"&gt;Breakpoint 1, 0x0040104f in foo ()
1: x/i $pc
0x40104f &amp;lt;_Z3food+7&amp;gt;:   flds   0x402030
(gdb) info float
  R7: Empty   0x3ffd9999999999999800
  R6: Empty   0x00e07c93022200240000
  R5: Empty   0x51c27c92fe956123a74c
  R4: Empty   0x79d37c9a06007c930460
  R3: Empty   0x0a887c9479870022bf80
  R2: Empty   0xbf9800010a886123debc
  R1: Empty   0x00006123a74c7c93043e
=&amp;gt;R0: Empty   0xdee46123de0c6123d8cc

Status Word:         0xffff0000
                       TOP: 0
Control Word:        0xffff037f   IM DM ZM OM UM PM
                       PC: Extended Precision (64-bits)
                       RC: Round to nearest
Tag Word:            0xffffffff
Instruction Pointer: 0x1b:0x004010c8
Operand Pointer:     0xffff0023:0x0022cd10
Opcode:              0xdd1c&lt;/pre&gt;

&lt;p&gt;我們將中斷點設在 foo() 函式，接著使用 info float 去 dump FPU 相關的 register (FPU 相關 register 似乎無法加到 gdb 的 Automatic Display！？所以每次都需手打 )，比較特別的幾個要點都被 highlight 了：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;R0 ～ R7 即剛剛提到的 FPU data register stack ： stack 目前是空的，雖然指向 R0 ，但顯示為 &lt;font color="#ff0000"&gt;Empty&lt;/font&gt; &lt;/li&gt;

  &lt;li&gt;Control Word 裡頭的 RC （rounding-control）決定了 floating-point 的進位（round）方式。 
    &lt;br /&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/THoZ9hiqLlI/AAAAAAAAA4Y/iMQS49LngIU/s1600-h/image17.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/THoZ-UJr6JI/AAAAAAAAA4c/W8BKTb3CWOE/image_thumb7.png?imgmax=800" width="644" height="282" /&gt;&lt;/a&gt;&amp;#160; &lt;br /&gt;節錄自： &lt;a href="http://www.intel.com/Assets/PDF/manual/253665.pdf" target="_blank"&gt;Intel® 64 and IA-32 Architectures Software Developer’s Manual ─ Volume 1: Basic Architecture&lt;/a&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;認識了 gdb 對於 FPU 的輸出後，可以開始一步步逼近問題核心 ── ebp-12 了。&lt;/p&gt;

&lt;p&gt;foo() 的一開始，是讀入 0x402030 上的值到 FPU stack 上：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [3];"&gt;Breakpoint 1, 0x0040104f in foo ()
1: x/i $pc
0x40104f &amp;lt;_Z3food+7&amp;gt;:   flds   0x402030&lt;/pre&gt;

&lt;p&gt;好奇這 magic number 是何來的，可以透過之前的 disassembly 結果：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [2];"&gt;LC1:
	.long	1101004800    ; = 0x41a00000
	.text
	.align 2&lt;/pre&gt;

&lt;p&gt;或是動態的用 debugger 觀看：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [2];"&gt;(gdb) x 0x402030
0x402030 &amp;lt;_data_start__+48&amp;gt;:    0x41a00000 ; = 1101004800&lt;/pre&gt;

&lt;p&gt;而 0x41a00000 便是 20.0 的 IEEE 754 0.3 的 IEEE 754 Double precision (64 bits) 表示式。來用 debugger 確認一下：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [3, 12, 20];"&gt;Breakpoint 1, 0x0040104f in foo ()
1: x/i $pc
0x40104f &amp;lt;_Z3food+7&amp;gt;:   flds   0x402030
(gdb) info float
  R7: Empty   0x3ffd9999999999999800
  R6: Empty   0x00e07c93022200240000
  R5: Empty   0x51c27c92fe956123a74c
  R4: Empty   0x79d37c9a06007c930460
  R3: Empty   0x0a887c9479870022bf80
  R2: Empty   0xbf9800010a886123debc
  R1: Empty   0x00006123a74c7c93043e
=&amp;gt;R0: Empty   0xdee46123de0c6123d8cc

(gdb) si
0x00401055 in foo ()
1: x/i $pc
0x401055 &amp;lt;_Z3food+13&amp;gt;:  fmull  0x8(%ebp)

(gdb) info float
=&amp;gt;R7: Valid   0x4003a000000000000000 +20
  R6: Empty   0x00e07c93022200240000&lt;/pre&gt;

&lt;p&gt;執行完上面的指令後， FPU 的 data stack 現在是 20 ，接著進行 x 0.3 的乘法（ebp+0x8 是 foo() 的參數，即 0.3）：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [1, 8];"&gt;0x401055 &amp;lt;_Z3food+13&amp;gt;:  fmull  0x8(%ebp)

(gdb) si
0x00401058 in foo ()
1: x/i $pc
0x401058 &amp;lt;_Z3food+16&amp;gt;:  fnstcw -0x6(%ebp)
(gdb) info float
=&amp;gt;R7: Valid   0x4001bffffffffffffe00 +6
  R6: Empty   0x00e07c93022200240000&lt;/pre&gt;

&lt;p&gt;得到了結果：+6 ，無誤。不過接下來的 FPU control word 卻令人意外：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [5, 15];"&gt;(gdb) info float
...
Control Word:        0xffff037f   IM DM ZM OM UM PM
                       PC: Extended Precision (64-bits)
                       RC: Round to nearest

0x40105f &amp;lt;_Z3food+23&amp;gt;:  or     $0xc00,%ax
0x401063 &amp;lt;_Z3food+27&amp;gt;:  mov    %ax,-0x8(%ebp)
0x401067 &amp;lt;_Z3food+31&amp;gt;:  fldcw  -0x8(%ebp)

(gdb) info float
...
Control Word:        0xffff0f7f   IM DM ZM OM UM PM
                       PC: Extended Precision (64-bits)
                       RC: Round toward zero&lt;/pre&gt;

&lt;p&gt;O 版將 RC 從 Round to nearest 改變成 Round toward zero 。這會影響到 fist 的運作。在執行 fist 前，我們把預期的結果： 6.0 的 IEEE 754 Double precision 求出來：0x4018000000000000 ；而目前的 R7 值是 0x4001bffffffffffffe00 ，小於該值。表示 R7 現在是不足 6.0 ，而此時又改以 Round toward zero 來進行取整數，那結果會是 5 則是預期了。&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [6, 11, 14, 21];"&gt;(gdb) si
0x0040106a in foo ()
1: x/i $pc
0x40106a &amp;lt;_Z3food+34&amp;gt;:  fistl  -0xc(%ebp)
(gdb) info float
=&amp;gt;R7: Valid   0x4001bffffffffffffe00 +6
  R6: Empty   0x4bc000010101e259acd0
...
Control Word:        0xffff0f7f   IM DM ZM OM UM PM
                       PC: Extended Precision (64-bits)
                       RC: Round toward zero

(gdb) x 0x22ccfc              ; ebp - 0xc = 0x22ccfc
0x22ccfc:       0x61100049

(gdb) si
0x0040106d in foo ()
1: x/i $pc
0x40106d &amp;lt;_Z3food+37&amp;gt;:  fldcw  -0x6(%ebp)
(gdb) x 0x22ccfc
0x22ccfc:       0x00000005&lt;/pre&gt;

&lt;p&gt;執行結果印證了我們的預期。&lt;/p&gt;

&lt;h2&gt;-ffloat-store 版&lt;/h2&gt;

&lt;p&gt;模仿取得 O 版 disassembly 的方式來取得 -ffloat-store 的結果：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;g++ -Wall -O -ffloat-store -S -masm=intel main.cpp&lt;/pre&gt;

&lt;p&gt;-ffloat-store 版和 O 版相同，會去呼叫 foo() ，不過比較兩者 foo() 可以發現： -ffloat-store 版只多了兩行，在進行 x 0.3 後，會馬上將值寫回 call stack 上，並再讀入。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/THoZ_G4uA0I/AAAAAAAAA4g/gq2YlZIdDyk/s1600-h/image%5B4%5D.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/THoZ_1kjn1I/AAAAAAAAA4k/H3lywFAFX_4/image_thumb%5B1%5D.png?imgmax=800" width="603" height="484" /&gt;&lt;/a&gt;也就是，當 6.0 被寫入記憶體時，是以 Round to nearest 的方式寫進：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [6, 11];"&gt;(gdb) si
0x00401058 in foo ()
1: x/i $pc
0x401058 &amp;lt;_Z3food+16&amp;gt;:  fstpl  -0x10(%ebp)
(gdb) info float
=&amp;gt;R7: Valid   0x4001bffffffffffffe00 +6
  R6: Empty   0xdbc000010101e4ada9d8
...
Control Word:        0xffff037f   IM DM ZM OM UM PM
                       PC: Extended Precision (64-bits)
                       RC: Round to nearest&lt;/pre&gt;

&lt;p&gt;而讀回 FPU stack 時，已經是個精確的 6.0 ：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [6,11];"&gt;(gdb) si
0x0040105e in foo ()
1: x/i $pc
0x40105e &amp;lt;_Z3food+22&amp;gt;:  fnstcw -0x12(%ebp)
(gdb) info float
=&amp;gt;R7: Valid   0x4001c000000000000000 +6
  R6: Empty   0x10000000000400010000
...
Control Word:        0xffff037f   IM DM ZM OM UM PM
                       PC: Extended Precision (64-bits)
                       RC: Round to nearest&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-6139783788809617027?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/6139783788809617027/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=6139783788809617027' title='3 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/6139783788809617027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/6139783788809617027'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2010/08/re-gcc-bug.html' title='Re: GCC Bug'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_2ZMoTkLFVu8/THoZ7XMH1FI/AAAAAAAAA4M/e94NXzfH_mY/s72-c/image_thumb1.png?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-4747503683486522468</id><published>2010-08-23T00:05:00.001+08:00</published><updated>2010-09-01T00:15:29.121+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Debugging'/><title type='text'>WinDbg 實驗： Command Line Arguments 的傳遞</title><content type='html'>&lt;p&gt;一個 C/C++ 程式可以透過 main() 的 argument list 取得 client 端輸入的 command line arguments：&lt;/p&gt;  &lt;pre class="brush: cpp;"&gt;int main( int argc, char* argv[] ) { ... }&lt;/pre&gt;

&lt;p&gt;如果好奇這是如何地&lt;em&gt;從無到有&lt;/em&gt;，可以寫一段程式碼來 trace 。&lt;/p&gt;

&lt;p&gt;先準備好 sample code:&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;

int main( int argc, char* argv[] )
{   // 程式的內容不是重點
    cout &amp;lt;&amp;lt; &amp;quot;hello world&amp;quot;;
    cin.get();
    return 0;
}&lt;/pre&gt;

&lt;p&gt;透過 VC++ 或是 WinDbg 在 main() 設定 breakpoint 來追蹤：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Compiler: VC++ 2005 &lt;/li&gt;

  &lt;li&gt;OS: Windows XP &lt;/li&gt;

  &lt;li&gt;在 cmd 中執行 CrtDemo05 test &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/TH0o8NlHL7I/AAAAAAAAA40/wFT8zoQEROo/s1600-h/image4%5B1%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/THFK5lrH9VI/AAAAAAAAA44/vLSWhWulb-U/image4_thumb.png?imgmax=800" width="484" height="195" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [17];"&gt;0:000&amp;gt; bp CrtDemo05!main
*** WARNING: Unable to verify checksum for CrtDemo05.exe

0:000&amp;gt; bl
 0 e 004377d0     0001 (0001)  0:**** CrtDemo05!main

0:000&amp;gt; g
Breakpoint 0 hit
eax=00383088 ebx=7ffda000 ecx=00383028 edx=00000001 esi=010df742 edi=010df6f2
eip=004377d0 esp=0012ff58 ebp=0012ffb8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
CrtDemo05!main:
004377d0 55              push    ebp

0:000&amp;gt; k
ChildEBP RetAddr  
0012ff54 0044a203 CrtDemo05!main [f:\src\_experiment\crtdemo05\crtdemo05\main.cpp @ 6]
0012ffb8 00449fbd CrtDemo05!__tmainCRTStartup+0x233 [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c @ 327]
0012ffc0 7c816d4f CrtDemo05!mainCRTStartup+0xd [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c @ 196]
0012fff0 00000000 kernel32!BaseProcessStart+0x23&lt;/pre&gt;

&lt;p&gt;進入 main() 之前的兩個函式都是 CRT 的一部分，負責完成基本但必要的初始化，舉凡 Global variables、Heap、I/O 等等都屬於這個範疇。這樣一來，身處 main() 後頭的我們才能順利工作。所以照這情勢看來，想知道 argument list 怎麼來，就得去 trace 這兩個 functions ，幸運的， VC++ CRT 的 source code 是隨著安裝程式散發的，通常就在：&lt;/p&gt;

&lt;p&gt;C:\Program Files\Microsoft Visual Studio 8\VC\crt&lt;/p&gt;

&lt;p&gt;視安裝路徑而定。也可以 double click VC++ 的 Call Stack 進入程式碼裡頭。&lt;/p&gt;

&lt;p&gt;如果想利用 debugger 追蹤或試驗 CRT ，不妨把 CRT link 改成 debug mode 並且是 static link 。這可以省下一些時間、增加 tracing 時的可讀性和便利性，因為像是 debug 下的 dynamic link 會使用 ILT ，它所引入的間接性，會讓定位 functions 或 symbols 徒增額外的時間，造成實驗的不便。&lt;/p&gt;

&lt;p&gt;VC++ 有所謂的 Microsoft C++ ，其程式進入點有自己的一套方式來定義，至少在名稱上，就可以找到四種：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;main &lt;/li&gt;

  &lt;li&gt;wmain &lt;/li&gt;

  &lt;li&gt;WinMain &lt;/li&gt;

  &lt;li&gt;wWinMain &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;不過它們使用的 CRT 是同一份程式碼，並且使用了跟 TCHAR.h 相同的手法來區別，但確實由 WPRFLAG 這個 macro 所控制凡；凡是見到 t、_t、__t 開頭的名稱，都有機會透過它來替換掉，不過 __tmainCRTStartup() 可說是例外。下表節錄與 command line 相關的 t、_t、_t 開頭 symbols:&lt;/p&gt;

&lt;table border="1" cellspacing="0" cellpadding="2" width="796"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td valign="top" width="142"&gt;&amp;#160;&lt;/td&gt;

      &lt;td valign="top" width="147"&gt;
        &lt;p align="center"&gt;ansi/console&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="164"&gt;
        &lt;p align="center"&gt;ansi/GUI&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="174"&gt;
        &lt;p align="center"&gt;wide/console&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="169"&gt;
        &lt;p align="center"&gt;wide/GUI&lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="142"&gt;
        &lt;p align="right"&gt;_tmainCRTStartup&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="147"&gt;
        &lt;p align="center"&gt;mainCRTStartup&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="164"&gt;
        &lt;p align="center"&gt;WinMainCRTStartup&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="174"&gt;
        &lt;p align="center"&gt;wmainCRTStartup&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="169"&gt;
        &lt;p align="center"&gt;wWinMainCRTStartup&lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="142"&gt;
        &lt;p align="right"&gt;_tcmdln&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="147"&gt;
        &lt;p align="center"&gt;_acmdln&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="164"&gt;
        &lt;p align="center"&gt;_acmdln&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="174"&gt;
        &lt;p align="center"&gt;_wcmdln&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="169"&gt;
        &lt;p align="center"&gt;_wcmdln&lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="142"&gt;
        &lt;p align="right"&gt;_targv&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="147"&gt;
        &lt;p align="center"&gt;__argv&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="164"&gt;
        &lt;p align="center"&gt;__argv&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="174"&gt;
        &lt;p align="center"&gt;__wargv&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="169"&gt;
        &lt;p align="center"&gt;__wargv&lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="142"&gt;
        &lt;p align="right"&gt;GetCommandLineT()&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="147"&gt;
        &lt;p align="center"&gt;GetCommandLineA&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="164"&gt;
        &lt;p align="center"&gt;GetCommandLineA&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="174"&gt;
        &lt;p align="center"&gt;__crtGetCommandLineW&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="169"&gt;
        &lt;p align="center"&gt;__crtGetCommandLineW&lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="142"&gt;
        &lt;p align="right"&gt;_tsetargv()&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="147"&gt;
        &lt;p align="center"&gt;_setargv&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="172"&gt;
        &lt;p align="center"&gt;_setargv&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="180"&gt;
        &lt;p align="center"&gt;_wsetargv&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="173"&gt;
        &lt;p align="center"&gt;_wsetargv&lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;我們先從 ansi 版的 main() ，也是 C/C++ Standard 所描述的 main() 開始：&lt;/p&gt;

&lt;h1&gt;mainCRTStartup()&lt;/h1&gt;

&lt;p&gt;mainCRTStartup() 基本上是一個 forward function ：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [4];"&gt;int _tmainCRTStartup( void )
{
    __security_init_cookie();
    return __tmainCRTStartup();
}&lt;/pre&gt;

&lt;h1&gt;__tmainCRTStartup()&lt;/h1&gt;

&lt;p&gt;就像前面提到的：__tmainCRTStartup() 就是正港的 __tmainCRTStartup() 沒有 ansi, wide 的替換，很快地就可以梳理出跟 command line 相關的程式：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [9, 14, 32];"&gt;int __tmainCRTStartup( void )
{
    // ...

    __try {
        // ...
    
        /* get wide cmd line info */
        _tcmdln = (_TSCHAR *)GetCommandLineT();

        /* get wide environ info */
        _tenvptr = (_TSCHAR *)GetEnvironmentStringsT();

        if ( _tsetargv() &amp;lt; 0 )
            _amsg_exit(_RT_SPACEARG);
        if ( _tsetenvp() &amp;lt; 0 )
            _amsg_exit(_RT_SPACEENV);

        // ...

    #ifdef _WINMAIN_
        lpszCommandLine = _twincmdln();
        mainret = _tWinMain( (HINSTANCE)&amp;amp;__ImageBase,
                             NULL,
                             lpszCommandLine,
                             StartupInfo.dwFlags &amp;amp; STARTF_USESHOWWINDOW
                                  ? StartupInfo.wShowWindow
                                  : SW_SHOWDEFAULT
                            );
    #else  /* _WINMAIN_ */
        _tinitenv = _tenviron;
        mainret = _tmain(__argc, _targv, _tenviron);
    #endif  /* _WINMAIN_ */

        // ...
    }
    __except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) ) {
        // ...
    }

    return mainret;
}&lt;/pre&gt;

&lt;p&gt;從上面的程式碼可以發現，重點就在於兩個 functions 上：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;GetCommandLineT() &lt;/li&gt;

  &lt;li&gt;_tsetargv() &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;但是當我們將 breakpoint 設在 GetCommandLineT() 時，卻無法 step in 。這時可以切換到 assembly 模式，透過 WinDbg diassembly window 或是 WinDbg 的 uf 幫助來持續追蹤：&lt;/p&gt;

&lt;pre&gt;0:000&amp;gt; uf __tmainCRTStartup
...
CrtDemo05!__tmainCRTStartup+0x1b4 [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c @ 300]:
  300 0044a184 ff1564924b00    &lt;font color="#ff0000"&gt;call    dword ptr [CrtDemo05!_imp__GetCommandLineA (004b9264)]&lt;/font&gt;
  300 0044a18a a3a4814b00      mov     dword ptr [CrtDemo05!_acmdln (004b81a4)],eax
  303 0044a18f e8a89efeff      call    CrtDemo05!ILT+55(___crtGetEnvironmentStringsA) (0043403c)
  303 0044a194 a3d45e4b00      mov     dword ptr [CrtDemo05!_aenvptr (004b5ed4)],eax
  305 0044a199 e87a9ffeff      call    CrtDemo05!ILT+275(__setargv) (00434118)
  305 0044a19e 85c0            test    eax,eax
  305 0044a1a0 7d0a            jge     CrtDemo05!__tmainCRTStartup+0x1dc (0044a1ac)
...&lt;/pre&gt;

&lt;p&gt;在 Windows 裡頭， _imp、__imp 開頭的 name mangling 代表： symbol 代表是從 DLL export 出的 ，可見 CrtDemo05!_imp__GetCommandLineA 存在與另外一個 DLL 之中。 dereference 該位址便可以找到真正的 symbol 。&lt;/p&gt;

&lt;pre&gt;0:000&amp;gt; dd &lt;font color="#ff0000"&gt;004b9264&lt;/font&gt;
004b9264  &lt;font color="#0080ff"&gt;7c812c8d&lt;/font&gt; 7c93043d 7c812851 7c9305d4
004b9274  7c80aa49 7c80a0c7 7c809cad 7c832e2b&lt;/pre&gt;

&lt;p&gt;由於 CrtDemo05 裡頭使用 call 來呼叫這個位址，想必這個位址會是一段可以執行的指令，使用 uf 來查找：&lt;/p&gt;

&lt;pre&gt;0:000&amp;gt; uf &lt;font color="#0080ff"&gt;7c812c8d&lt;/font&gt; 
kernel32!GetCommandLineA:
7c812c8d a1f435887c      mov     eax,dword ptr [&lt;font color="#008000"&gt;kernel32!BaseAnsiCommandLine+0x4 (7c8835f4)&lt;/font&gt;]
7c812c92 c3              ret&lt;/pre&gt;

&lt;p&gt;原來是落在 kernel32.dll 這個基礎函式庫裡頭，而且發現它的實做相當簡單：僅僅是從 kernel32!BaseAnsiCommandLine+0x4 位址讀取而已。為了驗證，我們以 dereference 該位址看是否真的儲存了要傳遞給 CrtDemo05 的 arguments 。&lt;/p&gt;

&lt;pre&gt;0:000&amp;gt; dd &lt;font color="#008000"&gt;7c8835f4&lt;/font&gt;
7c8835f4  &lt;font color="#800000"&gt;00151ee0&lt;/font&gt; 000a0008 7c80e300 ffff02ff
7c883604  00000001 000a0008 7c831874 000a0008&lt;/pre&gt;

&lt;p&gt;接著&lt;/p&gt;

&lt;pre&gt;0:000&amp;gt; da &lt;font color="#804040"&gt;00151ee0&lt;/font&gt; 
00151ee0  &amp;quot;C:\test\CrtDemo05.exe test&amp;quot;&lt;/pre&gt;

&lt;p&gt;若是覺得 dd 兩層的 dereference 有點麻煩，針對字串可以使用 dp* ，&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; dpa &lt;font color="#008000"&gt;7c8835f4&lt;/font&gt; L1
7c8835f4  001522f8 &amp;quot;CrtDemo05.exe&amp;quot;&lt;/pre&gt;

&lt;p&gt;無論是哪種方式，都驗證了我們的想法── kernel32!GetCommandLineA() 是取得 command line 的函式，並且有著極簡單的實做──讀取一個預先填好值的 variable。&lt;/p&gt;

&lt;p&gt;wmain() 版本也是相同的：&lt;/p&gt;

&lt;pre&gt;0:000&amp;gt; uf CrtDemo05!__tmainCRTStartup
...
CrtDemo05!__tmainCRTStartup+0x1b4 [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c @ 300]:
  300 0044a194 e8ad9efeff      &lt;font color="#ff0000"&gt;call    CrtDemo05!ILT+65(___crtGetCommandLineW) (00434046)&lt;/font&gt;
  300 0044a199 a3e4824b00      mov     dword ptr [CrtDemo05!_wcmdln (004b82e4)],eax
  303 0044a19e e8439ffeff      call    CrtDemo05!ILT+225(___crtGetEnvironmentStringsW) (004340e6)
  303 0044a1a3 a3d85e4b00      mov     dword ptr [CrtDemo05!_wenvptr (004b5ed8)],eax
  305 0044a1a8 e845b1feff      call    CrtDemo05!ILT+4845(__wsetargv) (004352f2)
  305 0044a1ad 85c0            test    eax,eax
  305 0044a1af 7d0a            jge     CrtDemo05!__tmainCRTStartup+0x1db (0044a1bb)
...&lt;/pre&gt;

&lt;p&gt;函式，你可能會好奇為什麼 wide 版本並不是呼叫 _imp__GetCommandLineW() ，其實它被包裝在 ___crtGetCommandLineW() 裡頭。&lt;/p&gt;

&lt;pre&gt;0:000&amp;gt; uf 00434046
...
CrtDemo05!__crtGetCommandLineW+0xf [f:\dd\vctools\crt_bld\self_x86\crt\src\aw_com.c @ 52]:
   52 0046336f ff1530934b00    call    dword ptr [CrtDemo05!&lt;font color="#ff0000"&gt;_imp__GetCommandLineW&lt;/font&gt; (&lt;font color="#0080ff"&gt;004b9330&lt;/font&gt;)]
   52 00463375 85c0            test    eax,eax
   52 00463377 740c            je      CrtDemo05!__crtGetCommandLineW+0x25 (00463385)
...&lt;/pre&gt;

&lt;p&gt;並且同樣地，可以使用如同 ansi 版本的方式，去 trace ：&lt;/p&gt;

&lt;pre&gt;0:000&amp;gt; dd &lt;font color="#0080ff"&gt;004b9330&lt;/font&gt;
004b9330  &lt;font color="#008000"&gt;7c816cfb&lt;/font&gt; 7c80c6cf 7c801eee 7c873d83
004b9340  7c81abe4 7c80180e 7c810da6 7c80cd58

0:000&amp;gt; uf &lt;font color="#008000"&gt;7c816cfb&lt;/font&gt; 
kernel32!GetCommandLineW:
7c816cfb a10430887c      mov     eax,dword ptr [kernel32!BaseUnicodeCommandLine+0x4 (&lt;font color="#8080ff"&gt;7c883004&lt;/font&gt;)]
7c816d00 c3              ret

0:000&amp;gt; dd &lt;font color="#8080ff"&gt;7c883004&lt;/font&gt;
7c883004  &lt;font color="#ff8080"&gt;0002062c&lt;/font&gt; 00000000 7c809784 7c80979d
7c883014  7c8097d2 7c8097e7 7c8097b7 00000000

0:000&amp;gt; du 0002062c 
0002062c  &amp;quot;C:\test\CrtDemo05.exe test&amp;quot;&lt;/pre&gt;

&lt;h1&gt;使用 Kernel Debugging&lt;/h1&gt;

&lt;p&gt;或許你會好奇為什麼 trace command 如何填入一個 process 需要動要到 kernel debug ？其實原因很簡單，因為當 user-mode debug 無法滿足時，以這次的參數傳遞來看，當我們利用 windbg 載入一個 program 時，program 需要執行到某個狀態後， user-mode debugger 才能介入，此時 arguments 已經設置完成。&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [19];"&gt;Microsoft (R) Windows Debugger Version 6.11.0001.404 X86
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: C:\test\CrtDemo05.exe
Symbol search path is: srv*C:\sym_cache*http://msdl.microsoft.com/download/symbols;C:\test
Executable search path is: 
ModLoad: 00400000 004bb000   CrtDemo05.exe
ModLoad: 7c920000 7c9b5000   ntdll.dll
ModLoad: 7c800000 7c91d000   C:\WINDOWS\system32\kernel32.dll
(7d8.568): Break instruction exception - code 80000003 (first chance)
eax=00251eb4 ebx=7ffd8000 ecx=00000001 edx=00000002 esi=00251f48 edi=00251eb4
eip=7c921230 esp=0012fb20 ebp=0012fc94 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ntdll!DbgBreakPoint:
7c921230 cc              int     3

0:000&amp;gt; kvn
 # ChildEBP RetAddr  Args to Child              
00 0012fb1c 7c95edc0 7ffdf000 7ffd8000 00000000 ntdll!DbgBreakPoint (FPO: [0,0,0])
01 0012fc94 7c941639 0012fd30 7c920000 0012fce0 ntdll!LdrpInitializeProcess+0xffa (FPO: [5,89,4])
02 0012fd1c 7c92eac7 0012fd30 7c920000 00000000 ntdll!_LdrpInitialize+0x183 (FPO: [Non-Fpo])
03 00000000 00000000 00000000 00000000 00000000 ntdll!KiUserApcDispatcher+0x7

0:000&amp;gt; da 00151ee0 
00151ee0  &amp;quot;C:\test\CrtDemo05.exe test&amp;quot;&lt;/pre&gt;

&lt;p&gt;注意到沒？當 CrtDemo05 整支程式還在被 OS 的 loader 所初始化時，在 __tmainCRTStartup 還未執行到之前，arguments 已經填入了。因此這個例子需要透過 kernel debugging 來進行更早期的追蹤。 kernel debugging 的方式有許多種，使用 VMWare 算是便利的方法之一，可以參考 &lt;a href="http://keikoblog.blogspot.com/2009/03/windows-debugging-kernel-debugging-with.html"&gt;Windows Debugging – Kernel Debugging with WinDbg and VMWare&lt;/a&gt; 設定環境。&lt;/p&gt;

&lt;h1&gt;Catch Me If You Can&lt;/h1&gt;

&lt;p&gt;為了捕捉 kernel32!BaseUnicodeCommanLine 以及 kernel32!BaseAnsiCommandLine 是如何被填寫的？我們可以透過 WinDbg 的 break on access ，不過很快就會遇到第一個問題：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; x kernel32!BaseUnicodeCommandLine
&lt;font color="#ff0000"&gt;7c885730&lt;/font&gt; kernel32!BaseUnicodeCommandLine = &amp;lt;no type information&amp;gt;
7c883000 kernel32!BaseUnicodeCommandLine = &amp;lt;no type information&amp;gt;&lt;/pre&gt;

&lt;p&gt;遇到兩個同名的 symbols ，理論上這是件會造成 symbol resolve 上 ambiguous 的事。雖然暫時無解，但幸運的是，根據之前追蹤結果：&lt;/p&gt;

&lt;p&gt;7c816cfb a10430887c mov eax,dword ptr [kernel32!BaseUnicodeCommandLine&lt;font color="#ff0000"&gt;+0x4&lt;/font&gt; (&lt;font color="#ff0000"&gt;7c883004&lt;/font&gt;)]&lt;/p&gt;

&lt;p&gt;我們可以直接選擇 &lt;font color="#ff0000"&gt;7c885730&lt;/font&gt; ：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; ba r4 &lt;font color="#ff0000"&gt;7c883004&lt;/font&gt;
kd&amp;gt; g
Breakpoint 0 hit
nt!MiCopyOnWrite+0x148:
0008:805222bc f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
kd&amp;gt; k
ChildEBP RetAddr  
b22bad00 8051d019 nt!MiCopyOnWrite+0x148
b22bad4c 805406ec nt!MmAccessFault+0x9f9
b22bad4c 7c93a100 nt!KiTrap0E+0xcc
0012f938 7c93d8a0 ntdll!__security_init_cookie_ex+0x31
0012f944 7c93d83a ntdll!LdrpInitSecurityCookie+0x2f
0012fa40 7c939b78 ntdll!LdrpRunInitializeRoutines+0x124
0012faf0 7c939ba0 ntdll!LdrpGetProcedureAddress+0x1c6
0012fb0c 7c942334 ntdll!LdrGetProcedureAddress+0x18
0012fc94 7c941639 ntdll!LdrpInitializeProcess+0xd7a
0012fd1c 7c92eac7 ntdll!_LdrpInitialize+0x183
00000000 00000000 ntdll!KiUserApcDispatcher+0x7&lt;/pre&gt;

&lt;p&gt;這一次還不是我們想要的 stack：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; g
Breakpoint 0 hit
kernel32!_BaseDllInitialize+0x20f:
7c817ea8 ff157c10807c    call    dword ptr [kernel32!_imp__RtlUnicodeStringToAnsiString (7c80107c)]
kd&amp;gt; bl
 0 e 7c883004 r 4 0001 (0001) kernel32!BaseUnicodeCommandLine+0x4
kd&amp;gt; k
ChildEBP RetAddr  
0012f918 7c9211a7 kernel32!_BaseDllInitialize+0x20f
0012f938 7c93cbab ntdll!LdrpCallInitRoutine+0x14
0012fa40 7c939b78 ntdll!LdrpRunInitializeRoutines+0x344
0012faf0 7c939ba0 ntdll!LdrpGetProcedureAddress+0x1c6
0012fb0c 7c942334 ntdll!LdrGetProcedureAddress+0x18
0012fc94 7c941639 ntdll!LdrpInitializeProcess+0xd7a
0012fd1c 7c92eac7 ntdll!_LdrpInitialize+0x183
00000000 00000000 ntdll!KiUserApcDispatcher+0x7&lt;/pre&gt;

&lt;p&gt;這次 stack 看起來成功率比較高。 disassembly 一段 breakpoint 前的程式碼，使用 WinDbg 的 disassembly 視窗或是指令都可以做到：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; ub 7c817ea8 L10
kernel32!_BaseDllInitialize+0x1cc:
...
7c817e7f 64a118000000    mov     &lt;font color="#8080ff"&gt;eax&lt;/font&gt;,dword ptr &lt;font color="#0080ff"&gt;fs:[00000018h]&lt;/font&gt;
7c817e85 8b4030          mov     &lt;font color="#0000ff"&gt;eax&lt;/font&gt;,dword ptr [&lt;font color="#800000"&gt;&lt;font color="#8080ff"&gt;eax&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;+30h&lt;/font&gt;]
7c817e88 8b4010          mov     &lt;font color="#008000"&gt;eax&lt;/font&gt;,dword ptr [&lt;font color="#0000ff"&gt;eax&lt;/font&gt;&lt;font color="#008000"&gt;+10h&lt;/font&gt;]
7c817e8b 8b4840          mov     &lt;font color="#ff0000"&gt;ecx&lt;/font&gt;,dword ptr [&lt;font color="#008000"&gt;eax&lt;/font&gt;&lt;font color="#ff0000"&gt;+40h&lt;/font&gt;]
7c817e8e 6a01            push    1
7c817e90 890d0030887c    mov     dword ptr [kernel32!BaseUnicodeCommandLine (7c883000)],&lt;font color="#ff0000"&gt;ecx&lt;/font&gt;
7c817e96 8b4044          mov     eax,dword ptr [eax+44h]
7c817e99 680030887c      push    offset kernel32!BaseUnicodeCommandLine (7c883000)
7c817e9e 68f035887c      push    offset kernel32!BaseAnsiCommandLine (7c8835f0)
7c817ea3 a30430887c      mov     dword ptr [kernel32!BaseUnicodeCommandLine+0x4 (7c883004)],eax&lt;/pre&gt;

&lt;h1&gt;解讀 fs:[00000018h]&lt;/h1&gt;

&lt;p&gt;可以發現，kernel32!BaseUnicodeCommandLine 是由 ecx 決定，而 ecx 則是由 fs:[00000018h] 所決定，這部份的解讀，需要一些的隱藏知識：在 x86 上Windows user mode 將每個 thread 的 TEB (Thread Environment Block)，存放在 fs:[0]；而在 kernel mode 中， fs:[0] 則是存放 KPCR (Process Control Region) 。&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [3];"&gt;kd&amp;gt; dt _TEB
ntdll!_TEB
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : Ptr32 Void
   +0x020 ClientId         : _CLIENT_ID
   +0x028 ActiveRpcHandle  : Ptr32 Void
   +0x02c ThreadLocalStoragePointer : Ptr32 Void
   +0x030 ProcessEnvironmentBlock : Ptr32 _PEB
   ...&lt;/pre&gt;

&lt;p&gt;整個 ntdll!_TEB 有點龐大，不過根據 ub 的結果，&lt;font color="#0080ff"&gt;fs:[00000018h] &lt;/font&gt;落在第一個欄位 ── _NT_TIB （Thread Information Block）裡頭，再進行一次 dt ：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [2, 10];"&gt;kd&amp;gt; dt _NT_TIB
ntdll!_NT_TIB
   +0x000 ExceptionList    : Ptr32 _EXCEPTION_REGISTRATION_RECORD
   +0x004 StackBase        : Ptr32 Void
   +0x008 StackLimit       : Ptr32 Void
   +0x00c SubSystemTib     : Ptr32 Void
   +0x010 FiberData        : Ptr32 Void
   +0x010 Version          : Uint4B
   +0x014 ArbitraryUserPointer : Ptr32 Void
   +0x018 Self             : Ptr32 _NT_TIB&lt;/pre&gt;

&lt;p&gt;那為何不直接使用 fs:[0] 而要選擇 &lt;font color="#0080ff"&gt;fs:[00000018h]&lt;/font&gt; ？因為 fs:[0] 並非 process 的 virtual address ：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; dd fs:0
003b:00000000  0012fa30 00130000 0012f000 00000000
003b:00000010  00001e00 00000000 7ffdd000 00000000
003b:00000020  00000778 00000128 00000000 00000000&lt;/pre&gt;

&lt;p&gt;因此使用上，往往透過 &lt;font color="#0080ff"&gt;fs:[00000018h] &lt;/font&gt;來指向正確 TEB 或說 TIB 的位址。&lt;/p&gt;

&lt;h1&gt;重新解讀 ub&lt;/h1&gt;

&lt;pre class="brush: cpp;"&gt;7c817e7f 64a118000000    mov     eax,dword ptr fs:[00000018h]
7c817e85 8b4030          mov     eax,dword ptr [eax+30h]
7c817e88 8b4010          mov     eax,dword ptr [eax+10h]
7c817e8b 8b4840          mov     ecx,dword ptr [eax+40h]&lt;/pre&gt;

&lt;p&gt;上述組語在知道 fs:[0] 的意義後，便可尋著指令進行 dt 的解碼，並寫出對應的虛擬碼：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;_TEB            teb = fs:[00000018h];
UNICODE_STRING  kernel32!BaseUnicodeCommandLine = 
    teb.ProcessEnvironmentBlock-&amp;gt;ProcessParameters.CommandLine;&lt;/pre&gt;

&lt;p&gt;到了這個步驟，我們已經知道即使是 kernel32!_BaseDllInitialize() 這般低階的初始化，也僅僅只是將 PEB 中的某個變數值讀出，那麼 PEB 中的值又是給負責填寫呢？還記得 Win32 API 中的 CreateProcess() 嗎？它或許是有嫌疑的一份子。&lt;/p&gt;

&lt;h1&gt;CreateProcess()&lt;/h1&gt;

&lt;pre class="brush: cpp; highlight: [15];"&gt;kd&amp;gt; dt _RTL_USER_PROCESS_PARAMETERS
ntdll!_RTL_USER_PROCESS_PARAMETERS
   +0x000 MaximumLength    : Uint4B
   +0x004 Length           : Uint4B
   +0x008 Flags            : Uint4B
   +0x00c DebugFlags       : Uint4B
   +0x010 ConsoleHandle    : Ptr32 Void
   +0x014 ConsoleFlags     : Uint4B
   +0x018 StandardInput    : Ptr32 Void
   +0x01c StandardOutput   : Ptr32 Void
   +0x020 StandardError    : Ptr32 Void
   +0x024 CurrentDirectory : _CURDIR
   +0x030 DllPath          : _UNICODE_STRING
   +0x038 ImagePathName    : _UNICODE_STRING
   +0x040 CommandLine      : _UNICODE_STRING
   +0x048 Environment      : Ptr32 Void
   +0x04c StartingX        : Uint4B
   +0x050 StartingY        : Uint4B
   +0x054 CountX           : Uint4B
   +0x058 CountY           : Uint4B
   +0x05c CountCharsX      : Uint4B
   +0x060 CountCharsY      : Uint4B
   +0x064 FillAttribute    : Uint4B
   +0x068 WindowFlags      : Uint4B
   +0x06c ShowWindowFlags  : Uint4B
   +0x070 WindowTitle      : _UNICODE_STRING
   +0x078 DesktopInfo      : _UNICODE_STRING
   +0x080 ShellInfo        : _UNICODE_STRING
   +0x088 RuntimeData      : _UNICODE_STRING
   +0x090 CurrentDirectores : [32] _RTL_DRIVE_LETTER_CURDIR&lt;/pre&gt;

&lt;p&gt;目前我們已經知道，一個程式的 command line 儲存在 _RTL_USER_PROCESS_PARAMETERS 這個 strcut 裡頭，所以要做的是，找到何時會去填寫，方法有兩種：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Trace CreateProcess &lt;/li&gt;

  &lt;li&gt;尋找有關 ProcessParameter 的 function 。 &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;我們使用方法 2. 來加速：&lt;/p&gt;

&lt;p&gt;可以使用 WinDbg 的 x 指令：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; x *!*processparameter*
&lt;font color="#ff0000"&gt;7c819f9e&lt;/font&gt; kernel32!BasePushProcessParameters = &amp;lt;no type information&amp;gt;
7c801488 kernel32!_imp__RtlCreateProcessParameters = &amp;lt;no type information&amp;gt;
7c801484 kernel32!_imp__RtlDestroyProcessParameters = &amp;lt;no type information&amp;gt;
7c9432ec ntdll!RtlDestroyProcessParameters = &amp;lt;no type information&amp;gt;
7c950ea3 ntdll!RtlCheckProcessParameters = &amp;lt;no type information&amp;gt;
7c9433c1 ntdll!RtlCreateProcessParameters = &amp;lt;no type information&amp;gt;&lt;/pre&gt;

&lt;p&gt;這幾個 functions 看起來都有機會，其中以 BasePushProcessParameters() 的名稱看來最有可能是 creater 建立 createe process parameter 的函式，為了驗證這想法，將 WinDbg 目前的 context 切換到 cmd.exe 下，並設定 breakpoint 來驗證：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; !process 0 0
**** NT ACTIVE PROCESS DUMP ****
...
PROCESS &lt;font color="#0080ff"&gt;8200d7e8&lt;/font&gt;  SessionId: 0  Cid: 0194    Peb: 7ffdf000  ParentCid: 0608
    DirBase: 08940240  ObjectTable: e1533828  HandleCount:  33.
    Image: cmd.exe

kd&amp;gt; .process /r /P /p &lt;font color="#0080ff"&gt;8200d7e8&lt;/font&gt;

kd&amp;gt; bp &lt;font color="#ff0000"&gt;7c819f9e&lt;/font&gt;

kd&amp;gt; g
Breakpoint 1 hit
kernel32!BasePushProcessParameters:
7c819f9e 68c0020000      push    2C0h

kd&amp;gt; k
ChildEBP RetAddr  
0013f028 7c8199bc kernel32!BasePushProcessParameters
0013fa88 7c80235e kernel32!CreateProcessInternalW+0x184e
0013fac0 4ad031dd kernel32!&lt;font color="#ff0000"&gt;CreateProcessW&lt;/font&gt;+0x2c
0013fc20 4ad02db0 cmd!ExecPgm+0x22b
0013fc54 4ad02e0e cmd!ECWork+0x84
0013fc6c 4ad05f9f cmd!ExtCom+0x40
0013fe9c 4ad013eb cmd!FindFixAndRun+0xcf
0013fee0 4ad0bbba cmd!Dispatch+0x137
0013ff44 4ad05164 cmd!main+0x216
0013ffc0 7c816d4f cmd!mainCRTStartup+0x125
0013fff0 00000000 kernel32!BaseProcessStart+0x23&lt;/pre&gt;

&lt;p&gt;stack 目前看來是支持我們的猜測， cmd.exe 透過 CreateProcess()&amp;#160; 來建立 CrtDemo05.exe ，並且呼叫 BasePushProcessParameters() 來初始化 process parameter。在這邊，我們也可以切換到 CrtDemo05.exe 下，確定一下它目前的建立狀態，以瞭解它仍是否仍在建立中而非建立完成：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; !process 0 0
**** NT ACTIVE PROCESS DUMP ****
...

PROCESS 8200d7e8  SessionId: 0  Cid: 0194    Peb: 7ffdf000  ParentCid: 0608
    DirBase: 08940240  ObjectTable: e1533828  HandleCount:  35.
    Image: cmd.exe

PROCESS 82476d00  SessionId: 0  Cid: 00c4    Peb: 7ffd4000  ParentCid: 0194
    DirBase: 089402c0  ObjectTable: e1d3bf68  HandleCount:  36.
    Image: conime.exe

PROCESS 8244e980  SessionId: 0  Cid: 05b4    Peb: 7ffdc000  ParentCid: 0400
    DirBase: 08940300  ObjectTable: e16e0700  HandleCount: 123.
    Image: wuauclt.exe

PROCESS &lt;font color="#ff0000"&gt;8244a460&lt;/font&gt;  SessionId: 0  Cid: 0224    Peb: &lt;font color="#ff80c0"&gt;7ffd5000&lt;/font&gt;  ParentCid: 0194
    DirBase: 08940380  ObjectTable: e17871a0  HandleCount:   1.
    Image: &lt;font color="#ff0000"&gt;CrtDemo0&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;看到 Image name 被截斷，有點訝異，不過可能是因為 kernel 在填寫時被我們中斷了。現在來看看 PEB 裡頭的 command line 是否已經準備好了：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; !peb &lt;font color="#ff8080"&gt;7ffd5000&lt;/font&gt;
PEB at 7ffd5000
error 1 InitTypeRead( nt!_PEB at 7ffd5000)...

kd&amp;gt; .process /r /P /p &lt;font color="#ff0000"&gt;8244a460&lt;/font&gt; 
Implicit process is now 8244a460
.cache forcedecodeuser done
Loading User Symbols
PEB is paged out (Peb.Ldr = 7ffd500c).  Type &amp;quot;.hh dbgerr001&amp;quot; for details
kd&amp;gt; dt _PEB 7ffd5000
nt!_PEB
   +0x000 InheritedAddressSpace : 0 ''
   +0x001 ReadImageFileExecOptions : 0 ''
   +0x002 BeingDebugged    : 0 ''
   +0x003 SpareBool        : 0 ''
   +0x004 Mutant           : 0xffffffff Void
   +0x008 ImageBaseAddress : 0x00400000 Void
   +0x00c Ldr              : (null) 
   +0x010 ProcessParameters : (null) 
   +0x014 SubSystemData    : (null) 
   +0x018 ProcessHeap      : (null) 
   +0x01c FastPebLock      : (null) 
   ...&lt;/pre&gt;

&lt;p&gt;試了兩種方法，都無法正確讀取 PEB ，這正和我們的預期：表示 CrtDemo05.exe 正在被建立中，其 PEB 似乎也在混沌之中。緊接著回到 cmd.exe 的 stack 上，接下來的事就需要點耐心，由於目前只知道 BasePushProcessParameters() 跟 _RTL_USER_PROCESS_PARAMETERS 有關，但是找不到可以設立 breakpoint 的地方，根據 assembly 一步步追蹤是個方法，不過直接閱讀 assembly 來找尋跟 ProcessParameters 相關的指令或許會更快，一個很快速的想法是使用關鍵字來縮小範圍，這裡若是使用 uf 來 diassembly ，可能會遇上一些麻煩，因為 CreateProcessInternalW() 被 OMAP 最佳化過，無法依照 mapping 到記憶體上的 layout 顯示：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; uf CreateProcessInternalW
Flow analysis was incomplete, some code may be missing
kernel32!CreateProcessInternalW+0x308:
...
...&lt;/pre&gt;

&lt;p&gt;當遇到這種狀況，我們得放棄 diassembly 整個 function ，而是直接指明記憶體位址：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; x kernel32!CreateProcessInternalW
&lt;font color="#ff0000"&gt;7c8191eb&lt;/font&gt; kernel32!CreateProcessInternalW = &lt;no type information&gt;

kd&amp;gt; u &lt;font color="#ff0000"&gt;7c8191eb&lt;/font&gt; L600
kernel32!CreateProcessInternalW:
...
; ProcessParameter
; ebp-234h: _RTL_USER_PROCESS_PARAMETERS*
&lt;font color="#0080ff"&gt;7c81a11d&lt;/font&gt; 8d85ccfdffff    lea     eax,[ebp-234h]
7c81a123 50              push    eax                        ; pProcessParameters
7c81a124 ff158814807c    call    dword ptr [kernel32!_imp__RtlCreateProcessParameters (7c801488)]
7c81a12a 33d2            xor     edx,edx                    ; edx = 0
7c81a12c 3bc2            cmp     eax,edx

...
...
&lt;font color="#008000"&gt;7c81a538&lt;/font&gt; ff158414807c    call    dword ptr [kernel32!_imp__RtlDestroyProcessParameters (7c801484)]&lt;/pre&gt;

&lt;p&gt;幸運的找到：&lt;/p&gt;

&lt;p&gt;7c9432ec ntdll!RtlDestroyProcessParameters 
  &lt;br /&gt;7c9433c1 ntdll!RtlCreateProcessParameters&lt;/p&gt;

&lt;p&gt;利用兩個 functions ，我們可以縮小可疑範圍，&lt;font color="#0080ff"&gt;7c81a11d&lt;/font&gt; ~ &lt;font color="#008000"&gt;7c81a538&lt;/font&gt; 給了我們一個暗示：ebp-234h 是個 local variable ，並且傳遞至 RtlCreateProcessParameters() ，當結束後進行是否為 NULL 的比較，那麼 ebp-234h 基本上就很有機會就是一個 pointer point to _RTL_USER_PROCESS_PARAMETERS。另外在向上回溯，可以找找看是否還有其他參數被傳遞至 RtlCreateProcessParameters() ：&lt;/p&gt;

&lt;pre class="brush: cpp; highlight: [3, 5, 7, 9, 10, 12, 17, 19, 21, 23];"&gt;7c81a0d7 ffd6            call    esi
7c81a0d9 8d85b4fdffff    lea     eax,[ebp-24Ch]
7c81a0df 50              push    eax                    ; parameter10
7c81a0e0 8d859cfdffff    lea     eax,[ebp-264h]
7c81a0e6 50              push    eax                    ; parameter9
7c81a0e7 8d85a4fdffff    lea     eax,[ebp-25Ch]
7c81a0ed 50              push    eax                    ; parameter8
7c81a0ee 8d8594fdffff    lea     eax,[ebp-26Ch]
7c81a0f4 50              push    eaxe                   ; parameter7
7c81a0f5 ffb570fdffff    push    dword ptr [ebp-290h]   ; parameter6
7c81a0fb 8d8584fdffff    lea     eax,[ebp-27Ch]
7c81a101 50              push    eax                    ; parameter5
7c81a102 f7db            neg     ebx
7c81a104 1bdb            sbb     ebx,ebx
7c81a106 8d8578fdffff    lea     eax,[ebp-288h]
7c81a10c 23d8            and     ebx,eax
7c81a10e 53              push    ebx                    ; parameter4
7c81a10f 8d85acfdffff    lea     eax,[ebp-254h]
7c81a115 50              push    eax                    ; parameter3
7c81a116 8d858cfdffff    lea     eax,[ebp-274h]
7c81a11c 50              push    eax                    ; parameter2
7c81a11d 8d85ccfdffff    lea     eax,[ebp-234h]
7c81a123 50              push    eax                    ; parameter1
7c81a124 ff158814807c    call    dword ptr [kernel32!_imp__RtlCreateProcessParameters (7c801488)]&lt;/pre&gt;

&lt;p&gt;看到了 10 個參數被傳遞至 RtlCreateProcessParameters() ，我們可以選擇 diassembly 它看是否有與 command line 相關的操作，或是繼續搜尋其他 &lt;font color="#0080ff"&gt;7c81a11d&lt;/font&gt; ~ &lt;font color="#008000"&gt;7c81a538&lt;/font&gt; 內 ebp-234h 的操作，這裡有一個或許可行的快速篩選法，因為 CommandLine 位於 _RTL_USER_PROCESS_PARAMETERS offset 40 bytes 的地方：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; dt _RTL_USER_PROCESS_PARAMETERS
ntdll!_RTL_USER_PROCESS_PARAMETERS
   ...
   &lt;font color="#ff0000"&gt;+0x040&lt;/font&gt; CommandLine      : _UNICODE_STRING
   ...&lt;/pre&gt;

&lt;p&gt;我們便找尋 40h 的關鍵字，而搜尋結果的確有幾筆與 40h 有關的操作，但幸運地，都不是和 CommandLine 有關的。於是乎，把焦點放回 RtlCreateProcessParameters()：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; x ntdll!RtlCreateProcessParameters
&lt;font color="#0080ff"&gt;7c9433c1&lt;/font&gt; ntdll!RtlCreateProcessParameters

kd&amp;gt; u &lt;font color="#0080ff"&gt;7c9433c1&lt;/font&gt; L200
ntdll!RtlCreateProcessParameters:
...
7c9435e1 6a04            push    4                          ; Protect
7c9435e3 6800100000      push    1000h                      ; AllocationType
7c9435e8 8d45cc          lea     eax,[ebp-34h]
7c9435eb 50              push    eax                        ; RegionSize
7c9435ec 53              push    ebx                        ; ZeroBits
7c9435ed 8d45e4          &lt;font color="#008000"&gt;lea     eax,[ebp-1Ch]&lt;/font&gt;
7c9435f0 50              &lt;font color="#008000"&gt;push    eax&lt;/font&gt;                        ; BaseAddress
7c9435f1 6aff            push    0FFFFFFFFh                 ; ProcessHandle
7c9435f3 e8e69efeff      call    ntdll!ZwAllocateVirtualMemory (7c92d4de)
...&lt;/pre&gt;

&lt;p&gt;由於 ZwAllocateVirtualMemory() 是公開的 API ，所以很快地可以對參數進行 mapping ，馬上就發現 local vaiable ebp-1ch 存放的就是 allocate 的結果，並且在稍後就有一個 +40h 的操作：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; u &lt;font color="#0080ff"&gt;7c9433c1&lt;/font&gt; L200
ntdll!RtlCreateProcessParameters:
...
7c94369a 40              inc     eax
7c94369b 40              inc     eax
7c94369c 50              push    eax
7c94369d 8b45e4          &lt;font color="#8080ff"&gt;mov     eax,dword ptr [ebp-1Ch]&lt;/font&gt;    ; pBase
&lt;font color="#ff8000"&gt;7c9436a0&lt;/font&gt; 83c040          &lt;font color="#8080ff"&gt;add     eax,40h&lt;/font&gt;                    ; pBase + 40 = CommandLine
7c9436a3 57              push    edi
7c9436a4 50              push    eax
7c9436a5 8d45d8          lea     eax,[ebp-28h]
7c9436a8 50              push    eax
7c9436a9 e8ab000000      call    ntdll!RtlpCopyProcString (7c943759)
...&lt;/pre&gt;

&lt;p&gt;這和 CommandLine 的操作看似吻合，但我們仍需要找到更直接的證據，首先可以使用動態的證據，也就是設定 breakpoint 去證明，我們將 breakpoint 先設定在 add eax,40h：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; bp &lt;font color="#ff8000"&gt;7c9436a0&lt;/font&gt;

kd&amp;gt; g
Breakpoint 2 hit
ntdll!RtlCreateProcessParameters+0x2f5:
7c9436a0 83c040          add     eax,40h

kd&amp;gt; dd &lt;font color="#8080ff"&gt;ebp-1c&lt;/font&gt;
0013ed00  00380000 0013ecd4 0013edf8 0013f018
0013ed10  7c92ee18 7c943748 00000000 0013f028

kd&amp;gt; dd 00380040 
00380040  &lt;font color="#00ff00"&gt;00000000 00000000&lt;/font&gt; 00010000 00000000
00380050  00000000 00000000 00000000 00000000&lt;/pre&gt;

&lt;p&gt;接著，執行數個指令後，等到 RtlpCopyProcString() 執行完成後：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; dd 00380040 
00380040  &lt;font color="#00ff00"&gt;00260024 003805c0&lt;/font&gt; 00010000 00000000
00380050  00000000 00000000 00000000 00000000

kd&amp;gt; du 003805c0
003805c0  &amp;quot;CrtDemo05.exe test&amp;quot;&lt;/pre&gt;

&lt;p&gt;再者，我們可以來個靜態分析：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; u &lt;font color="#0080ff"&gt;7c9433c1&lt;/font&gt; L200
ntdll!RtlCreateProcessParameters:
...
7c94370b 8b45e4          mov     &lt;font color="#ff8000"&gt;eax&lt;/font&gt;,dword ptr [&lt;font color="#8080ff"&gt;ebp-1Ch&lt;/font&gt;]
7c94370e 6689988a000000  mov     word ptr [eax+8Ah],bx
7c943715 ff75e4          push    dword ptr [&lt;font color="#8080ff"&gt;ebp-1Ch&lt;/font&gt;]
7c943718 e8f6fbffff      call    ntdll!RtlDeNormalizeProcessParams (7c943313)
7c94371d 8b4d08          mov     ecx,dword ptr [ebp+8]
7c943720 8901            mov     dword ptr [ecx],eax
...&lt;/pre&gt;

&lt;p&gt;很快地就有一個可疑的證物： ebp+8 也就是 RtlCreateProcessParameters() 的第一個參數，它被 eax 給賦值。雖然 eax 在第一行被指定為 &lt;font color="#8080ff"&gt;ebp-1Ch&lt;/font&gt; ，看似符合我們的假設，但因為中間有個 RtlDeNormalizeProcessParams() 的呼叫，不能掉以輕心，必須進去瞧瞧：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; uf RtlDeNormalizeProcessParams
Flow analysis was incomplete, some code may be missing
ntdll!RtlDeNormalizeProcessParams:
7c943313 8bff            mov     edi,edi
7c943315 55              push    ebp
7c943316 8bec            mov     ebp,esp
7c943318 8b4508          mov     &lt;font color="#808000"&gt;eax,dword ptr [ebp+8]&lt;/font&gt;
7c94331b 85c0            test    eax,eax
7c94331d 7478            je      ntdll!RtlDeNormalizeProcessParams+0x84 (7c943397)
...&lt;/pre&gt;

&lt;p&gt;幸運的， RtlDeNormalizeProcessParams() 沒有可觀的實作，也僅在 function 開頭將 eax 給予 ebp+8 所代表的位址；而 &lt;font color="#808000"&gt;ebp+8&lt;/font&gt; 也正就是&lt;font color="#8080ff"&gt; ebp-1Ch&lt;/font&gt;，其餘的對應操作都是 read 。確定了 RtlDeNormalizeProcessParams() 不會更改 &lt;font color="#8080ff"&gt;ebp-1Ch&lt;/font&gt; 後，就可以放心回到 RtlCreateProcessParameters()：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; u 7c9433c1 L200
ntdll!RtlCreateProcessParameters:
...
7c94345b 8b7d18          mov     edi,dword ptr [ebp+18h]
...
7c943685 e8cf000000      call    ntdll!RtlpCopyProcString (7c943759)
7c94368a 668b07          mov     ax,word ptr [edi]
7c94368d 663b4702        cmp     ax,word ptr [edi+2]
7c943691 0f84f79a0200    je      ntdll!RtlCreateProcessParameters+0x2e9 (7c96d18e)
7c943697 0fb7c0          movzx   eax,ax
7c94369a 40              inc     eax
7c94369b 40              inc     eax
&lt;font color="#ff0000"&gt;7c94369c&lt;/font&gt; 50              push    eax
7c94369d 8b45e4          mov     eax,dword ptr [ebp-1Ch]    ; pBase
7c9436a0 83c040          add     eax,40h                    ; pBase + 40 = CommandLine
7c9436a3 57              push    edi
7c9436a4 50              push    eax
7c9436a5 8d45d8          lea     eax,[ebp-28h]
&lt;font color="#008000"&gt;7c9436a8&lt;/font&gt; 50              push    eax
7c9436a9 e8ab000000      call    ntdll!RtlpCopyProcString (7c943759)&lt;/pre&gt;

&lt;p&gt;可以發現，可疑的參數有：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;7c94369a&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; inc eax 
    &lt;br /&gt;7c94369b&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; inc eax 

    &lt;br /&gt;&lt;font color="#ff0000"&gt;7c94369c&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push eax &lt;/li&gt;

  &lt;li&gt;7c94345b&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; mov edi,dword ptr [ebp+18h] 
    &lt;br /&gt;7c9436a3&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push edi &lt;/li&gt;

  &lt;li&gt;7c9436a5&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; lea eax,[ebp-28h] 
    &lt;br /&gt;&lt;font color="#008000"&gt;7c9436a8&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; push eax &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;為了找出實際的賦值給 ebp-1Ch+40h 的對象，這邊可以使用 breakpoint 去檢驗，分別是：&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; bp &lt;font color="#ff0000"&gt;7c94369c&lt;/font&gt;
kd&amp;gt; g
Breakpoint 5 hit
ntdll!RtlCreateProcessParameters+0x2f1:
7c94369c 50              push    eax
kd&amp;gt; r
eax=&lt;font color="#ff0000"&gt;00000026&lt;/font&gt; ebx=00000000 ecx=00380034 edx=00000000 esi=00000208 edi=&lt;font color="#0080ff"&gt;0013edac&lt;/font&gt;
eip=7c94369c esp=0013ecd4 ebp=0013ed1c iopl=0         nv up ei pl nz na po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000203

kd&amp;gt; dpu 0013edac+4 L1
0013edb0  0015adc8 &amp;quot;CrtDemo05.exe test&amp;quot;

kd&amp;gt; bp &lt;font color="#008000"&gt;7c9436a8&lt;/font&gt;
kd&amp;gt; g
Breakpoint 6 hit
kd&amp;gt; dd ebp-28h
0013ecf4  &lt;font color="#008000"&gt;003805c0&lt;/font&gt; 00000000 00000634 00380000
0013ed04  0013ecd4 0013edf8 0013f018 7c92ee18

kd&amp;gt; dpu &lt;font color="#008000"&gt;003805c0&lt;/font&gt;
003805c0  00000000&lt;/pre&gt;

&lt;p&gt;透過 breakpoint 的實驗，就可以知道 edi 才是賦值給 ebp-1Ch+40h 的來源，而且還是 RtlCreateProcessParameters() 的第五個參數。所以可以反推 edi 是怎麼來的，並一路反推，便可得到 command line 最初的來源。&lt;/p&gt;

&lt;pre&gt;kd&amp;gt; uf kernel32!CreateProcessW
kernel32!CreateProcessW:
7c802332 8bff            mov     edi,edi
7c802334 55              push    ebp
7c802335 8bec            mov     ebp,esp
7c802337 6a00            push    0                      ; parameter12
7c802339 ff752c          push    dword ptr [ebp+2Ch]    ; lpProcessInformation
7c80233c ff7528          push    dword ptr [ebp+28h]    ; lpStartupInfo
7c80233f ff7524          push    dword ptr [ebp+24h]    ; lpCurrentDirectory
7c802342 ff7520          push    dword ptr [ebp+20h]    ; lpEnvironment
7c802345 ff751c          push    dword ptr [ebp+1Ch]    ; dwCreationFlags
7c802348 ff7518          push    dword ptr [ebp+18h]    ; bInheritHandles
7c80234b ff7514          push    dword ptr [ebp+14h]    ; lpThreadAttributes
7c80234e ff7510          push    dword ptr [ebp+10h]    ; lpProcessAttributes
&lt;font color="#ff0000"&gt;7c802351 ff750c          push    dword ptr [ebp+0Ch]    ; lpCommandLine&lt;/font&gt;
7c802354 ff7508          push    dword ptr [ebp+8]      ; lpApplicationName
7c802357 6a00            push    0                      ; parameter1
7c802359 e88d6e0100      call    kernel32!CreateProcessInternalW (7c8191eb)
7c80235e 5d              pop     ebp
7c80235f c22800          ret     28h

kd&amp;gt; x kernel32!CreateProcessInternalW
7c8191eb kernel32!CreateProcessInternalW = &amp;lt;no type information&amp;gt;

kd&amp;gt; u 7c8191eb L600
kernel32!CreateProcessInternalW:
...
7c819214 8b4510          mov     &lt;font color="#008000"&gt;eax&lt;/font&gt;,dword ptr [&lt;font color="#ff0000"&gt;ebp+10h&lt;/font&gt;]    ; lpCommandLine
7c819217 8985e0f8ffff    mov     dword ptr [&lt;font color="#8080ff"&gt;ebp-720h&lt;/font&gt;],&lt;font color="#008000"&gt;eax&lt;/font&gt;
...
7c819958 8b8de0f8ffff    mov     &lt;font color="#0080ff"&gt;ecx&lt;/font&gt;,dword ptr [&lt;font color="#8080ff"&gt;ebp-720h&lt;/font&gt;]   ; lpCommandLine
...
7c819964 ffb56cf9ffff    push    dword ptr [ebp-694h]    ; parameter13
7c81996a ffb500f7ffff    push    dword ptr [ebp-900h]    ; parameter12
7c819970 8a85b7f8ffff    mov     al,byte ptr [ebp-749h]
7c819976 f6d8            neg     al
7c819978 1bc0            sbb     eax,eax
7c81997a 83e002          and     eax,2
7c81997d 50              push    eax                    ; parameter11
7c81997e ff751c          push    dword ptr [ebp+1Ch]    ; parameter10
7c819981 8b85f4f6ffff    mov     eax,dword ptr [ebp-90Ch]
7c819987 0b4520          or      eax,dword ptr [ebp+20h]
7c81998a 50              push    eax                     ; parameter9
7c81998b 8d8560f7ffff    lea     eax,[ebp-8A0h]
7c819991 50              push    eax                     ; parameter8
7c819992 ffb5b0f8ffff    push    dword ptr [ebp-750h]    ; parameter7
7c819998 51              push    &lt;font color="#0080ff"&gt;ecx&lt;/font&gt;                     ; parameter6
7c819999 ffb550f7ffff    push    dword ptr [ebp-8B0h]    ; parameter5
7c81999f ffb5e4f8ffff    push    dword ptr [ebp-71Ch]    ; parameter4
7c8199a5 ffb5b8f7ffff    push    dword ptr [ebp-848h]    ; parameter3
7c8199ab ffb594f9ffff    push    dword ptr [ebp-66Ch]    ; parameter2
7c8199b1 ffb534f7ffff    push    dword ptr [ebp-8CCh]    ; parameter1
7c8199b7 e8e2050000      call    kernel32!BasePushProcessParameters (7c819f9e)

kernel32!BasePushProcessParameters:
...
7c819fd3 8b4d1c          mov     ecx,dword ptr [ebp+1Ch]    ;
7c819fd6 898d5cfdffff    mov     dword ptr [&lt;font color="#ff8080"&gt;ebp-2A4h&lt;/font&gt;],&lt;font color="#0080ff"&gt;ecx&lt;/font&gt;   ; srcCmdLine
...
7c81a045 8d85d0fdffff    lea     eax,[ebp-230h]
7c81a04b 50              push    eax
7c81a04c 8d858cfdffff    lea     eax,[ebp-274h]
7c81a052 50              push    eax
7c81a053 ffd6            call    esi
7c81a055 ffb55cfdffff    push    dword ptr [&lt;font color="#ff8080"&gt;ebp-2A4h&lt;/font&gt;]   ; srcCmdLine
7c81a05b 8d8584fdffff    lea     &lt;font color="#800000"&gt;eax&lt;/font&gt;,[&lt;font color="#800000"&gt;ebp-27Ch&lt;/font&gt;]
7c81a061 50              push    &lt;font color="#800000"&gt;eax&lt;/font&gt;                    ; commandLine
7c81a062 ffd6            call    esi                    ; RtlInitUnicodeString
...
7c81a0cf 50              push    eax
7c81a0d0 8d8594fdffff    lea     eax,[ebp-26Ch]
7c81a0d6 50              push    eax
7c81a0d7 ffd6            call    esi
7c81a0d9 8d85b4fdffff    lea     eax,[ebp-24Ch]
7c81a0df 50              push    eax                        ; runtimeData
7c81a0e0 8d859cfdffff    lea     eax,[ebp-264h]
7c81a0e6 50              push    eax                        ; shellInfo
7c81a0e7 8d85a4fdffff    lea     eax,[ebp-25Ch]
7c81a0ed 50              push    eax                        ; desktopInfo
7c81a0ee 8d8594fdffff    lea     eax,[ebp-26Ch]
7c81a0f4 50              push    eax                        ; windowTitle
7c81a0f5 ffb570fdffff    push    dword ptr [ebp-290h]       ; environment
7c81a0fb 8d8584fdffff    lea     eax,[&lt;font color="#800000"&gt;ebp-27Ch&lt;/font&gt;]
7c81a101 50              push    eax                        ; commandLine, parameter5
7c81a102 f7db            neg     ebx
7c81a104 1bdb            sbb     ebx,ebx
7c81a106 8d8578fdffff    lea     eax,[ebp-288h]
7c81a10c 23d8            and     ebx,eax
7c81a10e 53              push    ebx                        ; currentDir
7c81a10f 8d85acfdffff    lea     eax,[ebp-254h]
7c81a115 50              push    eax                        ; dllPath
7c81a116 8d858cfdffff    lea     eax,[ebp-274h]
7c81a11c 50              push    eax                        ; imagePath
; ProcessParameter
; ebp-234h: _RTL_USER_PROCESS_PARAMETERS*
7c81a11d 8d85ccfdffff    lea     eax,[&lt;font color="#0000ff"&gt;ebp-234h&lt;/font&gt;]
7c81a123 50              push    eax                        ; pProcessParameters
7c81a124 ff158814807c    call    dword ptr [kernel32!_imp__RtlCreateProcessParameters (7c801488)]&lt;/pre&gt;

&lt;p&gt;最後，我們還沒來得及關心 creater 是如何的把 createe 的 PEB 建立完成，其實就在 RtlCreateProcessParameters() 稍後，透過 NtWriteVirtualMemory() 完成。&lt;/p&gt;

&lt;pre&gt;7c81a1eb 8b35f413807c    mov     &lt;font color="#8000ff"&gt;esi&lt;/font&gt;,dword ptr [kernel32!&lt;font color="#8000ff"&gt;_imp__NtWriteVirtualMemory&lt;/font&gt; (7c8013f4)]
...
7c81a38b 6a04            push    4                          ; Protect
7c81a38d bb00100000      mov     ebx,1000h
7c81a392 53              push    ebx                        ; AllocationtType
7c81a393 8d85c8fdffff    lea     eax,[ebp-238h]
7c81a399 50              push    eax                        ; RegionSize
7c81a39a 52              push    edx                        ; ZeroBits
7c81a39b 8d85c4fdffff    lea     eax,[ebp-23Ch]
7c81a3a1 50              push    eax                        ; BaseAddress
7c81a3a2 ffb580fdffff    push    dword ptr [ebp-280h]       ; hNewProcessHandle
7c81a3a8 8b3d9011807c    mov     &lt;font color="#8000ff"&gt;edi&lt;/font&gt;,dword ptr [kernel32!&lt;font color="#8000ff"&gt;_imp__NtAllocateVirtualMemory&lt;/font&gt; (7c801190)]
7c81a3ae ffd7            call    edi
7c81a3b0 898574fdffff    mov     dword ptr [ebp-28Ch],eax
7c81a3b6 8b85c8fdffff    mov     eax,dword ptr [ebp-238h]
7c81a3bc 898558fdffff    mov     dword ptr [ebp-2A8h],eax
7c81a3c2 83bd74fdffff00  cmp     dword ptr [ebp-28Ch],0
7c81a3c9 0f8c04950200    jl      kernel32!BasePushProcessParameters+0x504 (7c8438d3)
7c81a3cf 8b8dccfdffff    mov     ecx,dword ptr [ebp-234h]
7c81a3d5 8901            mov     dword ptr [ecx],eax
7c81a3d7 f6452b10        test    byte ptr [ebp+2Bh],10h
7c81a3db 0f85fa940200    jne     kernel32!BasePushProcessParameters+0x51d (7c8438db)
7c81a3e1 f6452b20        test    byte ptr [ebp+2Bh],20h
7c81a3e5 0f85ff940200    jne     kernel32!BasePushProcessParameters+0x52d (7c8438ea)
7c81a3eb f6452b40        test    byte ptr [ebp+2Bh],40h
7c81a3ef 0f8504950200    jne     kernel32!BasePushProcessParameters+0x53d (7c8438f9)
7c81a3f5 6a00            push    0                          ; nBytesWritten
7c81a3f7 8b85ccfdffff    mov     eax,dword ptr [&lt;font color="#0000ff"&gt;ebp-234h&lt;/font&gt;]
7c81a3fd ff7004          push    dword ptr [eax+4]          ; nBytesToWrite    : pProcParameters-&amp;gt;Length
7c81a400 50              push    eax                        ; Buffer           : pProcParameters
7c81a401 ffb5c4fdffff    push    dword ptr [ebp-23Ch]       ; BaseAddress      :
7c81a407 ffb580fdffff    push    dword ptr [ebp-280h]       ; hNewProcessHandle:
                                 ; NtWriteVirtualMemory( *(ebp-280h), *(ebp-23Ch), eax, ???, 0 )
7c81a40d ffd6            call    &lt;font color="#8000ff"&gt;esi&lt;/font&gt;                    ; _imp__NtWriteVirtualMemory&lt;/pre&gt;

&lt;p&gt;網路上可以找到人家 reverse 過的 RtlCreateProcessParameters() prototype 可以加速 trace 的速度：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;NTSTATUS RtlCreateProcessParameters( 
    PRTL_USER_PROCESS_PARAMETERS *ProcessParameters,
    PUNICODE_STRING     ImagePathName,
    PUNICODE_STRING     DllPath,
    PUNICODE_STRING     CurrentDirectory,
    PUNICODE_STRING     CommandLine,
    PWSTR               Environment, // Not sured
    PUNICODE_STRING     WindowTitle,
    PUNICODE_STRING     DesktopInfo,
    PUNICODE_STRING     ShellInfo,
    PUNICODE_STRING     RuntimeData );&lt;/pre&gt;

&lt;p&gt;不過如果想要硬派的自己來也是可以的，可以試試看這篇文章的作法 : )&lt;/p&gt;

&lt;h1&gt;Summary&lt;/h1&gt;

&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/THFMS_j0KEI/AAAAAAAAA3Y/LO8wkHAd3Nc/s1600-h/image%5B11%5D.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/THFMTjI5vVI/AAAAAAAAA3c/XXAIHVNfbNY/image_thumb%5B5%5D.png?imgmax=800" width="644" height="447" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-4747503683486522468?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/4747503683486522468/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=4747503683486522468' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4747503683486522468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4747503683486522468'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2010/08/windbg-command-line-arguments.html' title='WinDbg 實驗： Command Line Arguments 的傳遞'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_2ZMoTkLFVu8/THFK5lrH9VI/AAAAAAAAA44/vLSWhWulb-U/s72-c/image4_thumb.png?imgmax=800' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-8621537907492871924</id><published>2010-08-18T00:36:00.001+08:00</published><updated>2010-08-18T00:44:47.288+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>宜蘭行</title><content type='html'>&lt;p align="center"&gt;又為明日請假的衝動想到了一個理由 ── 整理照片，這檔事可是講衝動、帶感情的，時間過了就沒了！&lt;/p&gt;  &lt;p align="center"&gt;第一站是蘭陽博物館：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/TGq5sXlJfRI/AAAAAAAAA0E/-pXhV3h6Dt4/s1600-h/DSC058134.jpg"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="DSC05813" border="0" alt="DSC05813" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq5tGkEOnI/AAAAAAAAA0I/HNHaZbmQddI/DSC05813_thumb2.jpg?imgmax=800" width="644" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;蘭陽博物館的外觀造型很特別，在樸實的地方有著摩登的造型，讓人聯想起雪梨歌劇院和十三行博物館！不過歌劇&lt;/p&gt;  &lt;p align="center"&gt;院切片柳丁的圓弧造型，稍稍溫潤了點，不像蘭陽博物博物那麼地尖銳、直衝入天；十三行博物館則像無敵艦隊。&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/TGq5t633vfI/AAAAAAAAA0M/PtunkFaX9eY/s1600-h/DSC058264.jpg"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="DSC05826" border="0" alt="DSC05826" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/TGq5uh6IIqI/AAAAAAAAA0Q/OcRaTtzDxdg/DSC05826_thumb2.jpg?imgmax=800" width="644" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;博物館內相當不和諧，人山人海、萬頭鑽動，感覺這幾年，大家都體悟到：夏天就是&lt;/p&gt;  &lt;p align="center"&gt;博物館的季節！爸爸媽媽要帶小朋友到博物館走走，男女朋友也可以來趟知性之旅。&lt;/p&gt;  &lt;p align="center"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="DSC05817" border="0" alt="DSC05817" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/TGq5vWdVdWI/AAAAAAAAA0U/iV_HVvITSBE/DSC05817_thumb1.jpg?imgmax=800" width="644" height="484" /&gt;&lt;/p&gt;  &lt;p align="center"&gt;滿滿的人群是可以徹底粉碎、擊潰一個人排隊的決心！走到館外的陽台，大老遠地就可以看到泡泡在空&lt;/p&gt;  &lt;p align="center"&gt;中飄揚，外頭有個小朋友拿著電動吹泡泡機在玩。哈，和朋友不禁同聲讚道：太酷了！小時候關於泡泡&lt;/p&gt;  &lt;p align="center"&gt;的回憶都滿在一罐十元的綠瓶子裡。要看見泡泡隨風飛舞，光靠一個人是不可能的，畢竟一隻小手握著&lt;/p&gt;  &lt;p align="center"&gt;瓶子、一隻小手快速地在嘴前、瓶中切換，再快也快不上泡泡的消逝。使勁得吹啊！體力不好，吹著吹&lt;/p&gt;  &lt;p align="center"&gt;著就缺氧眼冒金星、口吐白沫去了～一旁的阿公還拿著專業填充罐，小時候葛葛可是都偷拿媽媽的洗碗&lt;/p&gt;  &lt;p align="center"&gt;精來用。猜猜有多少被這小朋友的神秘武器吸了眼球啊？&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/TGq5x586SZI/AAAAAAAAA0Y/Q9pMx09n1Hc/s1600-h/image20.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/TGq50-GHtHI/AAAAAAAAA0g/EOrncVXkBFA/image_thumb14.png?imgmax=800" width="644" height="457" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;拍了弟弟一會，對他留下蠻好的印象，他就是手舞足蹈地玩，夾雜著輕輕的笑，阿公、姊姊想從他手上&lt;/p&gt;  &lt;p align="center"&gt;拿走吹泡泡機時，也不會翻臉如翻書地哭給你看，或在地上翻滾，真是太乖巧伶俐了！對照最近在公車&lt;/p&gt;  &lt;p align="center"&gt;上遇見的小孩，鬼吼鬼叫的行徑真是有天壤之別，加上在一旁的父母也不教育一下，實在是 ooxx ，說&lt;/p&gt;  &lt;p align="center"&gt;來慚愧，正義感只是在心中蔓延，我也只是小峱峱 : (&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/TGq532PYJuI/AAAAAAAAA0k/kIDsSrJT5jM/s1600-h/image24.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/TGq56x5fJzI/AAAAAAAAA0o/DjZpzpmyCuQ/image_thumb16.png?imgmax=800" width="644" height="483" /&gt;&lt;/a&gt;&amp;#160; 拿泡泡機噴噴阿公、再噴噴我這個陌生人！&lt;/p&gt;  &lt;p align="center"&gt;（話說這張圖是用 PowerPoint 做的，用了 photoshop 和 illustrator &lt;/p&gt;  &lt;p align="center"&gt;之後發現，還是 PowerPoint 順手啊，誰叫我是工程師！）&lt;/p&gt;  &lt;p align="center"&gt;第二站是金車宜蘭噶瑪蘭威士忌酒廠。&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/TGq574RTs2I/AAAAAAAAA0s/WRxTcSaR7hk/s1600-h/DSC058322.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05832" border="0" alt="DSC05832" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq58fkzO0I/AAAAAAAAA0w/tKofUN4bWJ8/DSC05832_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt; &lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/TGq59RcBjjI/AAAAAAAAA00/To72nFTN3XU/s1600-h/DSC058312.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05831" border="0" alt="DSC05831" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq59-gRF8I/AAAAAAAAA04/F0tjLsAeKX4/DSC05831_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/TGq5-9N7qRI/AAAAAAAAA08/X8ZY83M3-x8/s1600-h/DSC058277.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05827" border="0" alt="DSC05827" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/TGq5_votx2I/AAAAAAAAA1A/WOwTNLcTzMI/DSC05827_thumb5.jpg?imgmax=800" width="644" height="484" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;  &lt;p align="center"&gt;雖然這景色沒有雄偉狀闊到黃河之水天上來的境界，不過應該也有小小的相識吧。&lt;/p&gt;  &lt;p align="center"&gt;想必這山谷就是傳說中造酒的水源？！宜蘭的好山好水被金車就用來造酒，也是種絕配。&lt;/p&gt;  &lt;p align="center"&gt;詩情畫意的風景佐以威士忌，挺不賴的吧！&lt;/p&gt;  &lt;p align="center"&gt;（身為好國民，就該響應一下政策宣導，請大家開車不喝酒、酒後不開車！）&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq6AeNL03I/AAAAAAAAA1E/isZsrgHII3U/s1600-h/DSC058342.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05834" border="0" alt="DSC05834" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/TGq6A_tmVYI/AAAAAAAAA1I/imZmvRdg8Yw/DSC05834_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt; &lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/TGq6CnVhW4I/AAAAAAAAA1M/akEkbU0E7f0/s1600-h/DSC058285.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05828" border="0" alt="DSC05828" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq6DJsghcI/AAAAAAAAA1Q/DBH4zzm1BNA/DSC05828_thumb1.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;整點左右到達酒廠可以跟上廠方的導覽，主要行程就是帶大家走走：蒸餾廠、酒堡。&lt;/p&gt;  &lt;p align="center"&gt;住宿：風箏民宿，&lt;a title="http://kite.ilanbnb.tw/" href="http://kite.ilanbnb.tw/"&gt;http://kite.ilanbnb.tw/&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;扣除給哈比人用的天花板外，風箏是間不錯的民宿，造型特別、離冬山河近、&lt;/p&gt;  &lt;p align="center"&gt;提供腳踏車、可以烤肉露營，老闆、老闆娘都蠻親切的，又是道地宜蘭人！&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/TGq6D_3-O2I/AAAAAAAAA1U/YanuZKuM3l8/s1600-h/DSC058513.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05851" border="0" alt="DSC05851" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/TGq6Eju8VtI/AAAAAAAAA1Y/KLCSTNGg-HM/DSC05851_thumb1.jpg?imgmax=800" width="644" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;ps. 這些小木屋都是蓋在水上！&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq6FavjUyI/AAAAAAAAA1c/7Ym2YTcQjys/s1600-h/DSC058543.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05854" border="0" alt="DSC05854" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq6F1pRYTI/AAAAAAAAA1g/VIpT2_2RLRY/DSC05854_thumb1.jpg?imgmax=800" width="364" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;那個，相當優秀的房客!!&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/TGq6Gsc5TNI/AAAAAAAAA1k/TDxPdHRK5v0/s1600-h/DSC058703.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05870" border="0" alt="DSC05870" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/TGq6HTeOnsI/AAAAAAAAA1o/4UJwzq-vP-s/DSC05870_thumb1.jpg?imgmax=800" width="364" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;該是騎腳踏車遊冬山河了。&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq6H4Xtn5I/AAAAAAAAA1s/HKc6__QC_NU/s1600-h/DSC058533.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05853" border="0" alt="DSC05853" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq6IWjPgwI/AAAAAAAAA1w/oKxq7xVCkJ8/DSC05853_thumb1.jpg?imgmax=800" width="364" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;天氣很熱，要找尋陰影處。瞧，這位聰明的朋友，趁著遊覽車司機&lt;/p&gt;  &lt;p align="center"&gt;抽煙小憩，偷偷躲在車影子下，不時還探頭看看司機抽完沒～&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq6JIQ4ifI/AAAAAAAAA10/0j4nwHa8c-k/s1600-h/DSC058573.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05857" border="0" alt="DSC05857" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/TGq6J9rzc3I/AAAAAAAAA14/OVUtnoOzlhQ/DSC05857_thumb1.jpg?imgmax=800" width="644" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/TGq6Kk8X6VI/AAAAAAAAA18/v8hvC5tNZ3M/s1600-h/DSC058585.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05858" border="0" alt="DSC05858" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq6LgkqTcI/AAAAAAAAA2A/q3Ug-NZP5fc/DSC05858_thumb3.jpg?imgmax=800" width="644" height="484" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p align="center"&gt;翻過這片大山，想必就是台北了吧?!&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq6MTmnKQI/AAAAAAAAA2E/l-vR3ialmYw/s1600-h/DSC058493.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05849" border="0" alt="DSC05849" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/TGq6NFTJiyI/AAAAAAAAA2I/fbn7w1kqF9s/DSC05849_thumb1.jpg?imgmax=800" width="644" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;有點不美，從此宜蘭成為台北的禁臠！來吧，一日遊的人們！（ps. 我們可是待了兩天～）&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/TGq6N0JU73I/AAAAAAAAA2M/TBGfC9IfWRE/s1600-h/DSC058723.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05872" border="0" alt="DSC05872" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/TGq6OSQcRmI/AAAAAAAAA2Q/X_DGjs9onUI/DSC05872_thumb1.jpg?imgmax=800" width="644" height="484" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/TGq6PY7eueI/AAAAAAAAA2U/XLU3dVpAL3k/s1600-h/DSC05873%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05873" border="0" alt="DSC05873" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/TGq6QEAtMCI/AAAAAAAAA2Y/hT0-eH6rL2k/DSC05873_thumb%5B1%5D.jpg?imgmax=800" width="344" height="259" /&gt;&lt;/a&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq6QobmiMI/AAAAAAAAA2c/L_mxOI4_kMI/s1600-h/DSC058775.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05877" border="0" alt="DSC05877" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq6RXIXBiI/AAAAAAAAA2g/6safH88vXpA/DSC05877_thumb3.jpg?imgmax=800" width="344" height="259" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;剛好碰到草坪水運！&lt;/p&gt;  &lt;h1 align="center"&gt;&lt;strong&gt;惡搞一下&lt;/strong&gt;&lt;/h1&gt;  &lt;p align="center"&gt;大概是整理照片最有趣的地方吧！&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/TGq6S_jOTDI/AAAAAAAAA2k/da6CnzK0B2I/s1600-h/image31.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/TGq6Wx17vtI/AAAAAAAAA2s/hoWskVa-NI8/image_thumb21.png?imgmax=800" width="581" height="772" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;&lt;font color="#494949"&gt;研究生的煩惱！&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/TGq6Y0Iw4DI/AAAAAAAAA2w/aWY25kx7vMk/s1600-h/image32.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq6crJ2tzI/AAAAAAAAA20/YhhpWRxmVtg/image_thumb22.png?imgmax=800" width="578" height="772" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;帥哥的煩惱！ &lt;/p&gt;  &lt;h1 align="center"&gt;&lt;strong&gt;空手奪白刃&lt;/strong&gt;&lt;/h1&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq6dnFiOCI/AAAAAAAAA24/rAG6KGjjbdE/s1600-h/DSC058794.jpg"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="DSC05879" border="0" alt="DSC05879" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/TGq6eAJ6o-I/AAAAAAAAA28/_-8MxcDbgt0/DSC05879_thumb2.jpg?imgmax=800" width="644" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h1 align="center"&gt;&lt;strong&gt;演出&lt;/strong&gt;&lt;/h1&gt;  &lt;p align="center"&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/TGq6e2bET3I/AAAAAAAAA3A/INoN8f_iPI4/s1600-h/DSC05890%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05890" border="0" alt="DSC05890" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/TGq6fpPnRRI/AAAAAAAAA3E/gq2wFFSaibY/DSC05890_thumb%5B1%5D.jpg?imgmax=800" width="364" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;強者我同事、司機兼攝影師、多情研究生。對了，還有神秘同事的女友（基於保護女性不予刊登），&lt;/p&gt;  &lt;p align="center"&gt;不知不覺竟然認識超過十年了。陳亦迅：&lt;em&gt;十年之前我不認識你…十年之後我們是朋友…&lt;/em&gt;這首歌實在很不搭嘎，&lt;/p&gt;  &lt;p align="center"&gt;可是每當想到認識十年，就會壞掉似的在心中哼起這首歌！&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-8621537907492871924?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/8621537907492871924/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=8621537907492871924' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/8621537907492871924'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/8621537907492871924'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2010/08/blog-post.html' title='宜蘭行'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_2ZMoTkLFVu8/TGq5tGkEOnI/AAAAAAAAA0I/HNHaZbmQddI/s72-c/DSC05813_thumb2.jpg?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-3979511393821004828</id><published>2010-07-10T01:58:00.001+08:00</published><updated>2010-07-10T01:58:49.548+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>Sharing 這回事</title><content type='html'>&lt;p&gt; Sharing 是先把自己掏空，再從聽講者身上充實自己。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-3979511393821004828?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/3979511393821004828/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=3979511393821004828' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3979511393821004828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3979511393821004828'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2010/07/sharing.html' title='Sharing 這回事'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-338519294251985028</id><published>2010-05-02T22:30:00.001+08:00</published><updated>2010-08-29T16:48:01.449+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RVO'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimization'/><title type='text'>Reduce NRV to RV</title><content type='html'>&lt;p&gt;或許不用到偏執的地步，人們就會某種程度上、或多或少地對於一個 return-by-value 的 function 感到憂心！&lt;/p&gt;  &lt;pre class="brush: cpp;"&gt;class MyClass {
    // ...
};

MyClass foo()
{
    // ...
}

int main()
{
    MyClass obj = foo();
}&lt;/pre&gt;

&lt;p&gt;憂慮其來有自：按照字面解讀，當 foo() 結束時，會將其結果放置於一個 temporary MyClass object 裡頭，並且這個 temporary object 會被作為 MyClass 的 copy constructor 的參數來初始化 obj 。若真如此，我們就不得不小心這類 return-by-value 的 function ，因為它引入了一個 temporary object 並且牽涉到 copy，temporary object 的建立與消滅可能對 performance 帶來極大的影響，舉例來說： MyClass 若是一個 1000x1000 的 array ，它的建立與消滅牽涉到大量的 heap allocation/deallocation ，遑論它還需要透過 copy constructor 把資料傳遞到另一個 object 上。&lt;/p&gt;

&lt;p&gt;不過事情並非想像中的那麼嚴重，現在許多的 compilers 都已經能某種程度地對 return-by-value 做出最佳化，以抑制 temporary object 和 copy 的發生，C++ Standard 中稱呼為 copy elision ； 一般則叫做 &lt;u&gt;r&lt;/u&gt;eturn &lt;u&gt;v&lt;/u&gt;alue optimization （RVO）。&lt;/p&gt;

&lt;h1&gt;Basic RVO&lt;/h1&gt;

&lt;p&gt;我們的目標是希望能夠抑制 copy 的發生，因此最好的情形就是：打從一開始，所作的運算就是在儲存結果的 destination object 上發生。要做到這點， compiler 大多使用一種簡單明瞭的方式：對 return-by-value 的 function prototype 動手腳，將它從&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;MyClass foo()
{
   // ...
}&lt;/pre&gt;

&lt;p&gt;轉換成：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;void foo( MyClass&amp;amp; result )
{
    // ...
}&lt;/pre&gt;

&lt;p&gt;如此一來，便有機會在 return-by-value 的 function 中直接操作 destination object 。在某些團隊裡頭，為了避免 performance drop ，往往會制定這樣的 coding standard ：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;不要讓一個 function 回傳一個 object，若真要如此，改將 object 當作 argument 傳給 function 進行處理。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;將 destination object 從 return value 轉移到 argument list 上，就像是手工式的最佳化。不過即使能直接操作 destination object ，要能做出正確的最佳化判斷仍然不是件簡單的事，參考一下這個 &lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm" target="_blank"&gt;N1377&lt;/a&gt; 的例子：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;A f( bool b )  
{  
    A a1, a2;  
    // ...  
    return b ? a1 : a2;  
} &lt;/pre&gt;

&lt;p&gt;Destination object 的 value 可能來自不同的 control flows 、不同的 source objects，若是 compiler 無法有好的對策來在 destination object 上生成有效率的運算，便可能迫使 compiler 放棄 RVO 。為此， communities 和 compilers 往往又在討論 RVO 時，將它分為兩類：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;u&gt;N&lt;/u&gt;amed &lt;u&gt;r&lt;/u&gt;eturn &lt;u&gt;v&lt;/u&gt;alue &lt;u&gt;o&lt;/u&gt;ptimization (NRVO)： Destination object 來自於一個 named （具名的）的變數，上述 &lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm" target="_blank"&gt;N1377&lt;/a&gt; 的例子就屬於 NRVO&amp;#160; 的範疇。 &lt;/li&gt;

  &lt;li&gt;Unnamed return value optimization：名稱上似乎沒有 URVO 這說法。 Destination object 來自於一個 unnamed （不具名的）的變數，通常就是那些直接存在於 return statement 上的 temporary objects。 &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;一般而言， compilers 對於 URV 的最佳化支援會比 NRV 好，因為它們往往不具備有太複雜的 control flow ，通常程式碼結構上就像：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;MyClass foo()
{
    return MyClass( &amp;quot;foo()&amp;quot; );
}&lt;/pre&gt;

&lt;p&gt;這般簡單，易於最佳化，因此即使是 g++ 不開啟最佳化或是 VC 2005 的 debug mode （預設是不啟用最佳化）， URVO 都是唾手可得的。不過 RVO 到底如何施行、能帶來多少效益，還是得視 compiler 而定，最好的策略還是得多瞭解自己工作的 compiler ，寫些程式去測試測試。當我寫這篇文章的時候，我測試了一下這樣的的程式碼：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;Config get( const std::string&amp;amp; input, const std::string&amp;amp; value )
{
    Config config;

    config.setName( input );
    config.setValue( value );
    config.setValue( 10 );

    return config;
}&lt;/pre&gt;

&lt;p&gt;即使這個 get() 只是：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;Config get( const std::string&amp;amp; input, const std::string&amp;amp; value )
{
    return Config( input, value );
}&lt;/pre&gt;
的惡搞版，會發現 NRV 很快地就讓 VC2005 debug mode 放棄 RVO ，但 g++4.4.1 -o0 還是能正常執行 RVO 。你可以參考這篇文章：&lt;a href="http://msdn.microsoft.com/en-us/library/ms364057%28VS.80%29.aspx" target="_blank"&gt;Named Return Value Optimization in Visual C++ 2005&lt;/a&gt;，知道更多關於 VC 2005 NRVO 的細節。 

&lt;h1&gt;Reduce NRV to RV&lt;/h1&gt;

&lt;p&gt;如前文所說，NRVO 屬於比較複雜的最佳化技術，並非每個 compiler 都提供。那麼在這種情況下，是不是代表著我們就只能妥協，將 return-by-value 變成 pass-by-reference 來手工模擬 compiler 的 transformation ，以減少 copy 的發生呢？不是的，有一個有趣的方式：將 NRV 轉換成 URV ，然後讓 compiler 去執行 URVO 。方法只要我們能提供特殊的 constructor ，並將運算放在裡頭。還記得我們一開始提到的精神：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;最好的情形就是：打從一開始，所作的運算就是在儲存結果的 destination object 上發生。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Reduce NRV to RV 就像是這個精神的衍生， class 的設計者為 class 提供能夠直接在 class object 上運算的能力。實作上， class 的設計者會提供一個或一組 constructors 讓運算直接由 class object 完成。&lt;/p&gt;

&lt;p&gt;舉例來說，一個 NRV function ：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;MyClass foo( int input, int filter )
{
    MyClass result;
    // Operations that involves result, intput, filter
    return result;
}&lt;/pre&gt;

&lt;p&gt;轉變為：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;MyClass foo( int input, int filter )
{
    return MyClass( input, filter );
}&lt;/pre&gt;

&lt;p&gt;因為 MyClass class 的設計者將 foo() 該執行的運算搬到了 constructor 裡頭：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;class MyClass {
public: 
    MyClass( int input, int filter )
    {
        // Initialize by input and filter
    }
};&lt;/pre&gt;

&lt;p&gt;那麼這麼做的缺點是什麼？嗯，一個不太自然的 constructor ，有點違反 data abstraction，而這個 MyClass 的可能充斥著各種具有這特殊功能的 constructors 。&lt;/p&gt;

&lt;h1&gt;A Mat8x8 Sample&lt;/h1&gt;

&lt;p&gt;如果想找個例子，不妨看看 &lt;a href="http://www.codeproject.com/KB/recipes/FasterCPPOperators.aspx" target="_blank"&gt;Faster C++ Operations&lt;/a&gt; [1]，它是一篇描述這種手工最佳化手法的文章，裡頭使用 Mat8x8 作為例子：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;class Mat8x8 {
    double  M[ 8*8 ];
public:
    Mat8x8()                      { memset( M, 0, 64*sizeof(double) ); }
    Mat8x8( const Mat8x8&amp;amp; other ) { memcpy( M, other.M, 512 ); }

    double&amp;amp; operator() ( int row, int col ) { return M[ row*8 + col ]; }

    Mat8x8&amp;amp; operator = ( const Mat8x8&amp;amp; rhs );
    Mat8x8  operator + ( const Mat8x8&amp;amp; rhs );
    Mat8x8  operator - ( const Mat8x8&amp;amp; rhs );
    Mat8x8  operator * ( double rhs );
    Mat8x8  operator / ( double rhs );
};&lt;/pre&gt;

&lt;p&gt;Mat8x8 支援了許多 built-in operators 的能力，我們只取 + 來看：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;Mat8x8::Mat8x8 operator + ( const Mat8x8&amp;amp; other ) {
    double Sum[64];
    for( int i=0; i&amp;lt;64; ++i )
        Sum[i] = M[i] + other.M[i];
    return Mat8x8( Sum );
    }&lt;/pre&gt;

&lt;p&gt;operator +() 是個典型的 NRV function ，在未能提供 NRVO 的 compiler 上，可能會產生對 performance 有所危害的程式，因此按照先前提到的 reduction ，我們需要為 Mat8x8 提供特殊的 constructor ，依照需求，這個 constructor 會是個接受兩個 arguments 的 constructors ，不過 Mat8x8 提供了不只是提供了 + 的運算，所以最好能夠連 –、*、/ 也一併處理，因此 &lt;a href="http://www.codeproject.com/KB/recipes/FasterCPPOperators.aspx" target="_blank"&gt;Faster C++ Operations&lt;/a&gt; [1] 提供的方法是利用具有古典優雅的氣息的 function pointer ，改寫之後變成：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;class Mat8x8 {
    typedef void (*PFnInitMat)( Mat8x8&amp;amp; Mat, void* pLHS, void* pRHS );

    // The special constructor help us to reduce NRV to RV
    Mat8x8( PFnInitMat Init, void* pLHS, void* pRHS )
    {
        Init( *this, pLHS, pRHS );
    }

public:
    union {
        double  M[8][8];
        double  A[ 64 ];
    };
    Mat8x8()                      { memset( A, 0, 64*sizeof(double) ); }
    Mat8x8( const Mat8x8&amp;amp; other ) { memcpy( A, other.A, 512 ); }

    Mat8x8&amp;amp; operator = ( const Mat8x8&amp;amp; rhs );
    Mat8x8  operator + ( const Mat8x8&amp;amp; rhs );
    Mat8x8  operator - ( const Mat8x8&amp;amp; rhs );
    Mat8x8  operator * ( double rhs );
    Mat8x8  operator / ( double rhs );
};

void AddMat88( Mat8x8&amp;amp; Mat, void* pLHS, void* pRHS )
{
    // ...
}

void SubMat88( Mat8x8&amp;amp; Mat, void* pLHS, void* pRHS )
{
    // ...
}

void DivMat88scalar( Mat8x8&amp;amp; Mat, void* pLHS, void* pRHS )
{
    // ...
}

void MulMat88scalar( Mat8x8&amp;amp; Mat, void* pLHS, void* pRHS )
{
    // ...
}&lt;/pre&gt;

&lt;p&gt;PFnInitMat 是個 function pointer type ，它代表了一族：可以接受兩個 Mat8x8 objects 並將結果寫於特定 object 的能力，家族成員包括： AddMat88()、SubMat88()、DivMat88()、MulMat88()。Mat8x8 class 現在有了一個特殊的 constructor ，它除了接受兩個 Mat8x8 的 arguments 外，還會接受一個 function pointer 來實際執行不同的運算。有了這樣的 constructor 幫忙，現在 operators 就會變成一個個簡單的 forward functions：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;Mat8x8 Mat8x8::operator + ( const Mat8x8&amp;amp; rhs ) {
    return Mat8x8( AddMat88, this, (void*)&amp;amp;rhs );
    }

Mat8x8 Mat8x8::operator - ( const Mat8x8&amp;amp; rhs ) {
    return Mat8x8( SubMat88, this, (void*)&amp;amp;rhs );
    }

Mat8x8 Mat8x8::operator * ( double rhs ) {
    return Mat8x8( MulMat88scalar, this, (pdouble)&amp;amp;rhs );
    }

Mat8x8 Mat8x8::operator / ( double rhs ) {
    return Mat8x8( DivMat88scalar, this, (pdouble)&amp;amp;rhs );
    }&lt;/pre&gt;

&lt;h1&gt;Generic Revision&lt;/h1&gt;

&lt;p&gt;看過了 &lt;a href="http://www.codeproject.com/KB/recipes/FasterCPPOperators.aspx" target="_blank"&gt;Faster C++ Operations&lt;/a&gt; [1] 的方式，不知道您有沒有什麼好奇的地方呢？ &lt;a href="http://fsfoundry.org/codefreak/"&gt;COdE fr3@K&lt;/a&gt; 跟我覺得有些地方可以來作些實驗：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Type safety：&lt;a href="http://www.codeproject.com/KB/recipes/FasterCPPOperators.aspx" target="_blank"&gt;Faster C++ Operations&lt;/a&gt; [1] 使用 void* 作為那些實際運算的 functions 的參數。因此在 AddMat88() 這類實際運算的 functions 裡頭，必須將 void* cast 成適當的 type ，少了那麼一點 type safety 的味道。或許有點吹毛求疵，不過引用作者的話： 

    &lt;br /&gt;I just used &lt;code&gt;void* &lt;/code&gt;for this example - they make programming flexible (under great responsibility). &lt;/li&gt;

  &lt;li&gt;Generic and parameterization operation ：實際運算的 functions 是透過 function pointers 傳遞 constructor 去執行任務，如果能改用 C++ 的一些泛型機制呢？ &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Generic and Parameterization Operations&lt;/h2&gt;

&lt;pre class="brush: cpp;"&gt;class Mat8x8 {
    struct plus_tag {
    };

    struct minus_tag {
    };

    struct division_tag {
    };

    struct multiplication_tag {
    };

    Mat8x8( const Mat8x8&amp;amp; lhs, const Mat8x8&amp;amp; rhs, plus_tag )
    {
        for ( size_t i = 0; i &amp;lt; 64; ++i ) {
            A[ i ] = lhs.A[ i ] + rhs.A[ i ];
        }
    }

    Mat8x8( const Mat8x8&amp;amp; lhs, const Mat8x8&amp;amp; rhs, minus_tag )
    {
        for ( size_t i = 0; i &amp;lt; 64; ++i ) {
            A[ i ] = lhs.A[ i ] - rhs.A[ i ];
        }
    }

    Mat8x8( const Mat8x8&amp;amp; lhs, double rhs, multiplication_tag )
    {
        for ( size_t i = 0; i &amp;lt; 64; ++i ) {
            A[ i ] = lhs.A[ i ] * rhs;
        }
    }

    Mat8x8( const Mat8x8&amp;amp; lhs, double rhs, division_tag )
    {
        for ( size_t i = 0; i &amp;lt; 64; ++i ) {
            A[ i ] = lhs.A[ i ] / rhs;
        }
    }

public:
    union {
        double  M[8][8];
        double  A[ 64 ];
    };

    Mat8x8()
    {
        memset( A, 0, 64*sizeof(double) );
    }

    Mat8x8( const Mat8x8&amp;amp; other )
    {
        cout &amp;lt;&amp;lt; &amp;quot;Copy ctor\n&amp;quot;;
        memcpy( A, other.A, 512 );
    }

    Mat8x8 operator + ( const Mat8x8&amp;amp; rhs )
    {
        return Mat8x8( *this, rhs, plus_tag() );
    }
    Mat8x8 operator - ( const Mat8x8&amp;amp; rhs )
    {
        return Mat8x8( *this, rhs, minus_tag() );
    }
    Mat8x8 operator * ( double rhs )
    {
        return Mat8x8( *this, rhs, multiplication_tag() );
    }
    Mat8x8 operator / ( double rhs )
    {
        return Mat8x8( *this, rhs, division_tag() );
    }
};&lt;/pre&gt;

&lt;p&gt;使用了幾個 tag classes 來幫助我們標示實際要求 constructor 執行的運算。不過這只是第一步，目前的實作還無法支援使用 Mat8x8 時，可以客製化運算，我們還需要做出這樣的修改：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;template &amp;lt;typename OperationT&amp;gt;
class Mat8x8 : public OperationT {
    struct plus_tag {
    };

    struct minus_tag {
    };

    struct division_tag {
    };

    struct multiplication_tag {
    };

    Mat8x8( const Mat8x8&amp;amp; lhs, const Mat8x8&amp;amp; rhs, plus_tag )
    {
        add( A, lhs.A, rhs.A );
    }

    Mat8x8( const Mat8x8&amp;amp; lhs, const Mat8x8&amp;amp; rhs, minus_tag )
    {
        minus( A, lhs.A, rhs.A );
    }

    Mat8x8( const Mat8x8&amp;amp; lhs, double rhs, multiplication_tag )
    {
        multiply( A, lhs.A, rhs );
    }

    Mat8x8( const Mat8x8&amp;amp; lhs, double rhs, division_tag )
    {
        divide( A, lhs.A, rhs );
    }

public:
    union {
        double  M[8][8];
        double  A[ 64 ];
    };

    Mat8x8()
    {
        memset( A, 0, 64*sizeof(double) );
    }

    Mat8x8( const Mat8x8&amp;amp; other )
    {
        cout &amp;lt;&amp;lt; &amp;quot;Copy ctor\n&amp;quot;;
        memcpy( A, other.A, 512 );
    }

    Mat8x8 operator + ( const Mat8x8&amp;amp; rhs )
    {
        return Mat8x8( *this, rhs, plus_tag() );
    }
    Mat8x8 operator - ( const Mat8x8&amp;amp; rhs )
    {
        return Mat8x8( *this, rhs, minus_tag() );
    }
    Mat8x8 operator * ( double rhs )
    {
        return Mat8x8( *this, rhs, multiplication_tag() );
    }
    Mat8x8 operator / ( double rhs )
    {
        return Mat8x8( *this, rhs, division_tag() );
    }
};&lt;/pre&gt;

&lt;p&gt;一個 policy-based class 來提供運算，並讓使用 Mat8x8 的人可以選擇要使用的矩陣計算方式；例如說最基本的運算可透過 MatOp class 來提供：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;struct MatOp {
    template &amp;lt;typename ValueT,
              size_t size&amp;gt;
    static void add( ValueT (&amp;amp;result)[ size ], const ValueT (&amp;amp;lhs)[ size ], const ValueT (&amp;amp;rhs)[ size ] )
    {
        for ( size_t i = 0; i &amp;lt; size; ++i ) {
            result[ i ] = lhs[ i ] + rhs[ i ];
        }
    }

    template &amp;lt;typename ValueT,
              size_t size&amp;gt;
    static void minus( ValueT (&amp;amp;result)[ size ], const ValueT (&amp;amp;lhs)[ size ], const ValueT (&amp;amp;rhs)[ size ] )
    {
        for ( size_t i = 0; i &amp;lt; size; ++i ) {
            result[ i ] = lhs[ i ] - rhs[ i ];
        }
    }

    template &amp;lt;typename ValueT,
              size_t size&amp;gt;
    static void multiply( ValueT (&amp;amp;result)[ size ], const ValueT (&amp;amp;lhs)[ size ], ValueT rhs )
    {
        for ( size_t i = 0; i &amp;lt; size; ++i ) {
            result[ i ] = lhs[ i ] * rhs;
        }
    }

    template &amp;lt;typename ValueT,
              size_t size&amp;gt;
    static void divide( ValueT (&amp;amp;result)[ size ], const ValueT (&amp;amp;lhs)[ size ], ValueT rhs )
    {
        for ( size_t i = 0; i &amp;lt; size; ++i ) {
            result[ i ] = lhs[ i ] / rhs;
        }
    }
};&lt;/pre&gt;

&lt;h2&gt;2010/05/03 Update&lt;/h2&gt;

&lt;p&gt;今天巧遇 &lt;a href="http://fsfoundry.org/codefreak/"&gt;COdE fr3@K&lt;/a&gt; ，他給了我幾個建議：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;少用繼承這種高耦合性的機制，尤其當你想描述的關係並非 is-a 而是 is-implemented-in-terms-of 。 &lt;/li&gt;

  &lt;li&gt;給 class template 一個名稱，並用 typedef 宣告另一個使用時的名稱。 &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;所以今天的作業 XD&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;template &amp;lt;typename OperationT&amp;gt;
class Mat8x8Base {
    struct plus_tag {
    };

    struct minus_tag {
    };

    struct division_tag {
    };

    struct multiplication_tag {
    };

    Mat8x8Base( const Mat8x8Base&amp;amp; lhs, const Mat8x8Base&amp;amp; rhs, plus_tag )
    {
        OperationT::add( A, lhs.A, rhs.A );
    }

    Mat8x8Base( const Mat8x8Base&amp;amp; lhs, const Mat8x8Base&amp;amp; rhs, minus_tag )
    {
        OperationT::minus( A, lhs.A, rhs.A );
    }

    Mat8x8Base( const Mat8x8Base&amp;amp; lhs, double rhs, multiplication_tag )
    {
        OperationT::multiply( A, lhs.A, rhs );
    }

    Mat8x8Base( const Mat8x8Base&amp;amp; lhs, double rhs, division_tag )
    {
        OperationT::divide( A, lhs.A, rhs );
    }

public:
    union {
        double  M[8][8];
        double  A[ 64 ];
    };

    Mat8x8Base()
    {
        memset( A, 0, 64*sizeof(double) );
    }

    Mat8x8Base( const Mat8x8Base&amp;amp; other )
    {
        cout &amp;lt;&amp;lt; &amp;quot;Copy ctor\n&amp;quot;;
        memcpy( A, other.A, 512 );
    }

    Mat8x8Base operator + ( const Mat8x8Base&amp;amp; rhs )
    {
        return Mat8x8( *this, rhs, plus_tag() );
    }
    Mat8x8Base operator - ( const Mat8x8Base&amp;amp; rhs )
    {
        return Mat8x8( *this, rhs, minus_tag() );
    }
    Mat8x8Base operator * ( double rhs )
    {
        return Mat8x8( *this, rhs, multiplication_tag() );
    }
    Mat8x8Base operator / ( double rhs )
    {
        return Mat8x8( *this, rhs, division_tag() );
    }
};

typedef Mat8x8Base&amp;lt;MatOp&amp;gt; Mat8x8;&lt;/pre&gt;

&lt;p&gt;以 Mat8x8Base 取代原本的 class template 名稱 Mat8x8 ，使用 typedef 宣告常用的名字 – Mat8x8 ；取消繼承，改用 qualified names 去呼叫 add(), minus() 之類的 functions。&lt;/p&gt;

&lt;h1&gt;C++0x 的救贖&lt;/h1&gt;

&lt;p&gt;真是的，說得口沫橫飛！其實重點在 C++0x 提供了 move semantics 幫助我們從 copy 的地獄中離開，&lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm" target="_blank"&gt;N1377&lt;/a&gt; ：&lt;/p&gt;

&lt;p&gt;Move semantics is mostly about performance optimization: the ability to move an expensive object from one address in memory to another, while pilfering resources of the source in order to construct the target with minimum expense.&lt;/p&gt;

&lt;p&gt;有興趣的，可以參考一下 &lt;a href="http://fsfoundry.org/codefreak/"&gt;COdE fr3@K&lt;/a&gt; 寫的一連串關於 move、r-value reference 的文章：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;C++0x: Rvalue References：&lt;a title="http://fsfoundry.org/codefreak/2008/11/16/cpp0x-rvalue-references/" href="http://fsfoundry.org/codefreak/2008/11/16/cpp0x-rvalue-references/"&gt;http://fsfoundry.org/codefreak/2008/11/16/cpp0x-rvalue-references/&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;C++0x: More on Rvalue References：&lt;a title="http://fsfoundry.org/codefreak/2008/11/16/cpp0x-more-on-rvalue-references/" href="http://fsfoundry.org/codefreak/2008/11/16/cpp0x-more-on-rvalue-references/"&gt;http://fsfoundry.org/codefreak/2008/11/16/cpp0x-more-on-rvalue-references/&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;I Like to Move It：&lt;a title="http://fsfoundry.org/codefreak/2009/05/19/i-like-to-move-it/" href="http://fsfoundry.org/codefreak/2009/05/19/i-like-to-move-it/"&gt;http://fsfoundry.org/codefreak/2009/05/19/i-like-to-move-it/&lt;/a&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;Furthermore&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;RVO vs. NRVO vs. URVO？ 
    &lt;br /&gt;前面提過，比較少有 URVO 這樣的稱呼，這篇文章會做這樣的區別，只是單純覺得 RVO 應該是包涵性較 NRVO 和 URVO 廣泛的最佳化，URVO 只能算是 RVO 裡頭較簡單的一種形式，不過許多文章談及 RVO 可能只牽涉到 URVO ，或者它們說是 apply RVO to unnamed temporaries [6]。 &lt;/li&gt;

  &lt;li&gt;為什麼 C++ Standard 會特別的定義 copy elision 呢？ 
    &lt;br /&gt;無論是 C++03 或是 C++0x 都會特別提及 copy elision ： 

    &lt;br /&gt;

    &lt;p&gt;When certain criteria are met, an implementation is &lt;font color="#ff0000"&gt;allowed to omit the copy/move construction of a class object&lt;/font&gt;, even if the copy/move constructor and/or destructor for the object have side effects. … . This elision of copy/move operations,&amp;#160; called &lt;em&gt;&lt;font color="#ff0000"&gt;copy elision&lt;/font&gt;&lt;/em&gt;,&amp;#160; is permitted in the following circumstances&lt;/p&gt;

    &lt;p&gt;因為一旦 copy elision 施行，原本發生在 return value 上的 side effect 也就不可得，雖然少見，但或許真有程式碼倚賴這樣的 side effect ，object counting 可能算是一類？！但為了效率的追求， RVO 是必要的，弭平爭議的方法就是在 standard 中好好說明。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;Reference&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Faster C++ Operators: &lt;a title="http://www.codeproject.com/KB/recipes/FasterCPPOperators.aspx" href="http://www.codeproject.com/KB/recipes/FasterCPPOperators.aspx"&gt;http://www.codeproject.com/KB/recipes/FasterCPPOperators.aspx&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;Named Return Value Optimization in Visual C++ 2005: &lt;a title="http://msdn.microsoft.com/en-us/library/ms364057%28VS.80%29.aspx" href="http://msdn.microsoft.com/en-us/library/ms364057%28VS.80%29.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms364057%28VS.80%29.aspx&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;N1377 A Proposal to Add Move Semantics Support to the C++ Language: &lt;a title="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm"&gt;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;The Name Return Value Optimization: &lt;a title="http://blogs.msdn.com/slippman/archive/2004/02/03/66739.aspx" href="http://blogs.msdn.com/slippman/archive/2004/02/03/66739.aspx"&gt;http://blogs.msdn.com/slippman/archive/2004/02/03/66739.aspx&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;C++ FAQ – 10. Constructors: &lt;a title="http://www.parashift.com/c++-faq-lite/ctors.html" href="http://www.parashift.com/c++-faq-lite/ctors.html"&gt;http://www.parashift.com/c++-faq-lite/ctors.html&lt;/a&gt;&amp;#160; &lt;/li&gt;

  &lt;li&gt;Move Constructors: &lt;a title="http://www.drdobbs.com/cpp/184403855#3" href="http://www.drdobbs.com/cpp/184403855#3"&gt;http://www.drdobbs.com/cpp/184403855#3&lt;/a&gt; &lt;/li&gt;
&lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-338519294251985028?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/338519294251985028/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=338519294251985028' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/338519294251985028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/338519294251985028'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2010/05/reduce-nrv-to-rv.html' title='Reduce NRV to RV'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-4046015309727567259</id><published>2010-02-19T17:36:00.001+08:00</published><updated>2010-02-19T17:42:11.354+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Book'/><title type='text'>DIY 書套</title><content type='html'>&lt;p align="center"&gt;&amp;#160;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35azSaVHXI/AAAAAAAAAoA/WiXA6YNuHCA/s1600-h/DSC05765_rescale%5B13%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05765_rescale" border="0" alt="DSC05765_rescale" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35a0MJ_RPI/AAAAAAAAAoE/aRDEoKMNlHE/DSC05765_rescale_thumb%5B7%5D.jpg?imgmax=800" width="364" height="174" /&gt;&lt;/a&gt; &lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35a0zQp-nI/AAAAAAAAAoI/n05Xr9n8rhY/s1600-h/DSC05764_rescale%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05764_rescale" border="0" alt="DSC05764_rescale" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35a1t4TlRI/AAAAAAAAAoM/8eZhJEVOfZc/DSC05764_rescale_thumb%5B3%5D.jpg?imgmax=800" width="364" height="175" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;不喜歡書本高高低低的，尤其還是同一家出版社的，這樣買書套很麻煩。不過離開小學後，好像只剩漫畫書比較容易塞進書套裡頭。&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h1&gt;工具 &lt;/h1&gt;  &lt;p&gt;先簡單知道一下什麼是：（參考&lt;a href="http://teach.mlc.edu.tw/~lib2004/p1.html" target="_blank"&gt;這裡&lt;/a&gt;和&lt;a href="http://192.192.169.101/reading/face/face.htm" target="_blank"&gt;這裡&lt;/a&gt;）&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;封面 &lt;/li&gt;    &lt;li&gt;封底 &lt;/li&gt;    &lt;li&gt;書背&amp;#160; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;請先準備：&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35a2wAA5uI/AAAAAAAAAoQ/lH86Ts6J18k/s1600-h/prepare%5B9%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="prepare" border="0" alt="prepare" align="right" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35a3rM7h7I/AAAAAAAAAoU/57owth9uOTw/prepare_thumb%5B5%5D.jpg?imgmax=800" width="364" height="188" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;font color="#0080ff"&gt;書套&lt;/font&gt;：不知道有沒有比較正式的名稱，平時我都去重慶南路上的亞典書局買的，不過這分店已經&lt;a href="http://blog.roodo.com/artlandbon/archives/8565127.html" target="_blank"&gt;結束營業&lt;/a&gt;了，唉！他們店內販售的外文書籍也是用這種書套包起來。&amp;#160;&amp;#160; &lt;/li&gt;    &lt;li&gt;&lt;font color="#0080ff"&gt;切割尺&lt;/font&gt;：它有一面鑲有鐵片，不怕切割時刮到，上頭也有許多方格幫忙定位，價錢有點高。&amp;#160;&amp;#160; &lt;/li&gt;    &lt;li&gt;&lt;font color="#0080ff"&gt;長尺&lt;/font&gt;：切割尺比較沉，有時候切割上不方便，準備一把短些、靈活的長尺比較方便，當然也要找上頭有方格的。 &lt;/li&gt;    &lt;li&gt;&lt;font color="#0080ff"&gt;刀片&lt;/font&gt;：好的刀片很重要～ &lt;/li&gt;    &lt;li&gt;&lt;font color="#0080ff"&gt;紙膠帶&lt;/font&gt;：很多膠帶會脫膠，會讓書本黑黑、黏黏的，紙膠帶是不錯的選擇。 &lt;/li&gt;    &lt;li&gt;&lt;font color="#0080ff"&gt;電池&lt;/font&gt;：不一定要是電池，只要能用來壓線、方便靈活就可以。 &lt;/li&gt; &lt;/ol&gt;  &lt;h1&gt;動手吧～&lt;/h1&gt;  &lt;p align="center"&gt;&amp;#160;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35a5Hf8vfI/AAAAAAAAAsQ/OWFg5inKqY4/s1600-h/Step1%5B10%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="Step1" border="0" alt="Step1" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35a6MSEPUI/AAAAAAAAAsU/NkQqBo35vAM/Step1_thumb%5B8%5D.jpg?imgmax=800" width="364" height="274" /&gt;&lt;/a&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35a7JEr8oI/AAAAAAAAAsc/y8WLa8_88Rk/s1600-h/Step2%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step2" border="0" alt="Step2" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35a8Nx-B2I/AAAAAAAAAsg/Qs-lTXMZhMk/Step2_thumb%5B2%5D.jpg?imgmax=800" width="364" height="274" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;Step1. 把書放在&lt;font color="#0080ff"&gt;書套&lt;/font&gt;上&lt;font color="#0080ff"&gt;偏右&lt;/font&gt;，上下約莫留 &lt;font color="#0080ff"&gt;8cm&lt;/font&gt; （視喜好而定），然後裁割。&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35a9Iv-lQI/AAAAAAAAAoo/-B5jTcSDX2w/s1600-h/Step3%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step3" border="0" alt="Step3" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35a-GL4RmI/AAAAAAAAAos/RBXj-goucoU/Step3_thumb%5B1%5D.jpg?imgmax=800" width="484" height="364" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;Step2. 以&lt;font color="#0080ff"&gt;書背為基準&lt;/font&gt;，把書本“橋”到&lt;font color="#0080ff"&gt;書套中間&lt;/font&gt;。&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35a_D9yKhI/AAAAAAAAAow/J9BnvoLUV_M/s1600-h/Step3-b%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step3-b" border="0" alt="Step3-b" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35a_kGOhBI/AAAAAAAAAo0/eJPP5l--MNM/Step3-b_thumb%5B1%5D.jpg?imgmax=800" width="364" height="274" /&gt;&lt;/a&gt; &lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35bAzdNkBI/AAAAAAAAAo4/XGLJQ-gmFLw/s1600-h/Step3-a%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step3-a" border="0" alt="Step3-a" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35bBiVCXcI/AAAAAAAAAo8/ag9fDRK-Wz0/Step3-a_thumb%5B1%5D.jpg?imgmax=800" width="364" height="274" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;Step3. 這邊，我們從&lt;font color="#0080ff"&gt;封面&lt;/font&gt;做起，&lt;font color="#0080ff"&gt;書背&lt;/font&gt;朝自己，大約捏出一條&lt;font color="#0080ff"&gt;折線&lt;/font&gt;。&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35bCh2UmlI/AAAAAAAAApA/WOcM2PCyDGU/s1600-h/Step4-a%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step4-a" border="0" alt="Step4-a" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35bDCpmbDI/AAAAAAAAApE/f8oSy9TH_b0/Step4-a_thumb%5B1%5D.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&amp;#160;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35bEEg-gGI/AAAAAAAAApI/-yLwPwspvNA/s1600-h/Step4-b%5B8%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step4-b" border="0" alt="Step4-b" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35bEjYkznI/AAAAAAAAApM/FhiGu7Pjr0w/Step4-b_thumb%5B2%5D.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35bFn2WrqI/AAAAAAAAApQ/hZDfozsD2x0/s1600-h/Step4-c%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step4-c" border="0" alt="Step4-c" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35bGe5-oBI/AAAAAAAAApU/SNpakljon0A/Step4-c_thumb%5B1%5D.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt; &lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35bHFt3brI/AAAAAAAAApY/7Ini0aKqewY/s1600-h/Step4-d%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step4-d" border="0" alt="Step4-d" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35bH5pW9gI/AAAAAAAAApc/CcVIICeor0w/Step4-d_thumb%5B1%5D.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;Step4. 把封面翻過來朝桌面，再壓一次折線，這&lt;font color="#0080ff"&gt;折線&lt;/font&gt;很重要，等會密不密實都靠它了。&lt;font color="#0080ff"&gt;電池&lt;/font&gt;這邊派上用場了，用來壓實，這可是用手指無法比擬的。&lt;/p&gt;  &lt;p align="center"&gt;&amp;#160;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35bIxWHlzI/AAAAAAAAApg/Q-4FFK3vGBo/s1600-h/Step5-a%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step5-a" border="0" alt="Step5-a" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35bJeQWqaI/AAAAAAAAApk/6HbJUH6meso/Step5-a_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt; &lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35bKciQvkI/AAAAAAAAApo/UTB7kM09LA8/s1600-h/Step5-b%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step5-b" border="0" alt="Step5-b" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35bLG0sD8I/AAAAAAAAAps/05-hQUeh_Rg/Step5-b_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;Step5. 稍微把書本後退，然後再用&lt;font color="#0080ff"&gt;電池壓實折線&lt;/font&gt;，最後也可以把書本退開，從頭用電池再壓一次。用這麼多次，知道這折線有多重要了吧？！&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35bMGh3aJI/AAAAAAAAApw/gNccVY8q5y8/s1600-h/Step6%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step6" border="0" alt="Step6" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35bM_amzII/AAAAAAAAAp0/K3HcD0x9QX4/Step6_thumb%5B1%5D.jpg?imgmax=800" width="364" height="274" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;Step6. 封底也是同樣作法。這邊忘了拍一張照片作為參考，不過可以看上圖：把&lt;font color="#0000ff"&gt;藍線&lt;/font&gt;以右假裝沒看到，就是封面、封底跑完 Step4 ~ 5 後的樣子。&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35bNiOOjcI/AAAAAAAAAp4/vmMeeQjqOTA/s1600-h/Step7%5B7%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step7" border="0" alt="Step7" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35bOVaJDiI/AAAAAAAAAp8/iUsyfFk7ggk/Step7_thumb%5B3%5D.jpg?imgmax=800" width="364" height="274" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;Step7. 準備裁掉過長的部份，這邊用&lt;font color="#0080ff"&gt;長尺&lt;/font&gt;和&lt;font color="#0080ff"&gt;書底&lt;/font&gt;做出一個直角，然後用刀片切出一條線。總共有&lt;font color="#0080ff"&gt;四條線要切&lt;/font&gt;。&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35bPWO0JFI/AAAAAAAAAqA/Rj7FMdLiuAs/s1600-h/Step8-a%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step8-a" border="0" alt="Step8-a" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35bQBWJPNI/AAAAAAAAAqE/3vTwbE7IDYI/Step8-a_thumb%5B1%5D.jpg?imgmax=800" width="364" height="274" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;  &lt;p align="center"&gt;Step8-a. 四條線切完後，把書本拿開，但&lt;font color="#0080ff"&gt;不要把兩旁折頁（紅色區域）打開&lt;/font&gt;，就會像上圖一樣，隱隱約約還可以看到切線（&lt;font color="#0000ff"&gt;藍色&lt;/font&gt;表示）。&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35bRI7kV9I/AAAAAAAAAqI/67eG4nB-llM/s1600-h/Step8-b%5B7%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step8-b" border="0" alt="Step8-b" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35bRyZmjNI/AAAAAAAAAqM/dJDGLlrsqp8/Step8-b_thumb%5B3%5D.jpg?imgmax=800" width="364" height="274" /&gt;&lt;/a&gt;&amp;#160; &lt;br /&gt;Step8-b. 將書套壓平，基於兩點成一直線的原理，我們已經可以知道書的上下緣線。沿著藍線頂點構成的紅線下刀。但別急著把尺移開。&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35bSxXL9UI/AAAAAAAAAqQ/GT8rI4smGgE/s1600-h/Step9-a%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step9-a" border="0" alt="Step9-a" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35bTl3p6rI/AAAAAAAAAqU/--2agVqLosY/Step9-a_thumb%5B1%5D.jpg?imgmax=800" width="364" height="274" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;  &lt;p align="center"&gt;Step9-a. 尺夠長的話，可以看到它橫跨過書套的折頁，也就是書的緣線，&lt;font color="#0080ff"&gt;輕輕劃過，做個劃線記號就好&lt;/font&gt;，除非刀功一流，保證不會割到隔一層的書套去。&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35bUnWj4II/AAAAAAAAAqY/W1cmTDZhi20/s1600-h/Step9-b%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step9-b" border="0" alt="Step9-b" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35bVkcK3TI/AAAAAAAAAqc/OFcwI5Zz0Sw/Step9-b_thumb%5B1%5D.jpg?imgmax=800" width="364" height="274" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;Step9-b. 四個角落都輕劃過完，可以看到 Step9-a 的劃線和 Step5 的折線形成一個四邊形，就裁掉它們吧～&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35bWbYWa1I/AAAAAAAAAqg/Cf4214wvSY4/s1600-h/Step9-c%5B8%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step9-c" border="0" alt="Step9-c" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35bXAVHlUI/AAAAAAAAAqk/moYjOyuBsaA/Step9-c_thumb%5B4%5D.jpg?imgmax=800" width="364" height="274" /&gt;&lt;/a&gt;&amp;#160;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35bX1QkXjI/AAAAAAAAAqo/NBkdJ5P_DAw/s1600-h/Step9-d%5B7%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step9-d" border="0" alt="Step9-d" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35bYhQEppI/AAAAAAAAAqs/6TF4HCMGKVA/Step9-d_thumb%5B3%5D.jpg?imgmax=800" width="206" height="274" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;Step9-c. 看到這個像雙十字的形狀了嗎？這就是書套的形狀了。這時有個修正的機會，&lt;font color="#0080ff"&gt;以紅線為準，去切掉不直的藍&lt;/font&gt;線。這誤差通常來自書套沒壓平，所以往往尾端會有些許多出來。&lt;/p&gt;  &lt;p align="center"&gt;&amp;#160;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35bZVtTiHI/AAAAAAAAAqw/PAjaBOsh-CU/s1600-h/Step10-a%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step10-a" border="0" alt="Step10-a" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35bZ74BxQI/AAAAAAAAAq0/I__OhikG7OU/Step10-a_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt; &lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35ba90MdRI/AAAAAAAAAq4/NW36uj68NbQ/s1600-h/Step10-b%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step10-b" border="0" alt="Step10-b" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35bbowu66I/AAAAAAAAAq8/oXudWpOatxw/Step10-b_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;Step10-a. 先把書套折頁翻過去，再把上下兩邊的折頁蓋上去。&lt;/p&gt;  &lt;p align="center"&gt;&amp;#160;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35bcvoXQ4I/AAAAAAAAArA/1ltDj1Ih5XI/s1600-h/Step10-c%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step10-c" border="0" alt="Step10-c" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35bdMKc4RI/AAAAAAAAArE/oU7HD-3DUFI/Step10-c_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35bd46qpVI/AAAAAAAAArI/tZAiqpWIwUc/s1600-h/Step10-d%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step10-d" border="0" alt="Step10-d" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35beZuo3mI/AAAAAAAAArM/rnOUzFpMo2E/Step10-d_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;Step10-b. 一樣用電池密實。&lt;font color="#0080ff"&gt;封面、封點都要做過一遍&lt;/font&gt;。&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35bfNLbKxI/AAAAAAAAArQ/wm6cz5zMhWo/s1600-h/Step11-a%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step11-a" border="0" alt="Step11-a" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35bfz33iMI/AAAAAAAAArU/Fq1iNnxtudw/Step11-a_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&amp;#160; &lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35bhEhehVI/AAAAAAAAArY/3UMPt7nVfxc/s1600-h/Step11-b%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step11-b" border="0" alt="Step11-b" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35bhkl2joI/AAAAAAAAArc/0tp2BPumZxs/Step11-b_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35bil-w5pI/AAAAAAAAArg/q3kp6waqhtY/s1600-h/Step11-c%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step11-c" border="0" alt="Step11-c" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35bjRab_PI/AAAAAAAAArk/V2mkXF254Nc/Step11-c_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;Step11. 把書本拿回來，&lt;font color="#0080ff"&gt;部份放入書套&lt;/font&gt;，套過書本的幫忙，可以方便地用&lt;font color="#0080ff"&gt;紙膠帶將折頁固定&lt;/font&gt;，之後再把封底完整放入書套。已經完成一邊了！&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/S35bkQ8XHpI/AAAAAAAAAro/moT6-gC7QJw/s1600-h/Step12-a%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step12-a" border="0" alt="Step12-a" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35bk9YOBYI/AAAAAAAAArs/ubqNkhpoj74/Step12-a_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35bli-oEyI/AAAAAAAAArw/h6vPm_Ubx3I/s1600-h/Step12-b%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step12-b" border="0" alt="Step12-b" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35bmKLhZvI/AAAAAAAAAr0/5d_JWYxq0BE/Step12-b_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35bnOtFNJI/AAAAAAAAAr4/4lbWVgdkYNg/s1600-h/Step12-c%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step12-c" border="0" alt="Step12-c" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35bnlIVq0I/AAAAAAAAAr8/ZxAQv39jVzQ/Step12-c_thumb%5B1%5D.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p align="center"&gt;Step12. 把書本翻到另一面，同時把書套折頁放入，利用書的重量一次整理一邊的上下折頁。過程中，手指記得把上下折頁的外緣用力拉往中間。&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/S35boVqsqII/AAAAAAAAAsA/Sh6bv1Uw3gQ/s1600-h/Step13%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Step13" border="0" alt="Step13" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35bpOuD76I/AAAAAAAAAsE/qDzlV5wkFHw/Step13_thumb%5B1%5D.jpg?imgmax=800" width="364" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;成果！不放心可以拿東西壓一壓，讓書套定型。&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/S35bqfEuh8I/AAAAAAAAAsI/KErMHnXJsRg/s1600-h/DSC05760%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSC05760" border="0" alt="DSC05760" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/S35brXDJELI/AAAAAAAAAsM/VNrdCkx5DfI/DSC05760_thumb%5B1%5D.jpg?imgmax=800" width="644" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;我都這樣用 &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx" target="_blank"&gt;Windows Internals&lt;/a&gt; 的~&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-4046015309727567259?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/4046015309727567259/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=4046015309727567259' title='8 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4046015309727567259'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4046015309727567259'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2010/02/diy.html' title='DIY 書套'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_2ZMoTkLFVu8/S35a0MJ_RPI/AAAAAAAAAoE/aRDEoKMNlHE/s72-c/DSC05765_rescale_thumb%5B7%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-1919850990521399843</id><published>2010-02-08T00:01:00.001+08:00</published><updated>2010-02-08T00:13:45.543+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Interrupt Handling'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Debugging'/><title type='text'>Interrupt Handling in Windows —— part 1: Using WinDbg</title><content type='html'>&lt;p&gt;透過 WinDbg 的 &lt;font color="#0080ff"&gt;!idt&lt;/font&gt;&lt;/font&gt; 指令，我們可以看到 IDT 的內容：&lt;/p&gt;  &lt;pre&gt;0: kd&amp;gt; !idt

Dumping IDT:

37:    806e6864 hal!PicSpuriousService37
3d:    806e7e2c hal!HalpApcInterrupt
41:    806e7c88 hal!HalpDispatchInterrupt
50:    806e693c hal!HalpApicRebootService
62:    81bbe6f4 atapi!IdePortInterrupt (KINTERRUPT 81bbe6b8)
63:    8191a974 USBPORT!USBPORT_InterruptService (KINTERRUPT 8191a938)
             portcls!CKsShellRequestor::`scalar deleting destructor'+0x26 (KINTERRUPT 8197cbb0)
73:    81962bec USBPORT!USBPORT_InterruptService (KINTERRUPT 81962bb0)
82:    81bd4bec atapi!IdePortInterrupt (KINTERRUPT 81bd4bb0)
83:    81be1ae4 SCSIPORT!ScsiPortInterrupt (KINTERRUPT 81be1aa8)
93:    81965204 i8042prt!I8042KeyboardInterruptService (KINTERRUPT 819651c8)
a3:    81964044 i8042prt!I8042MouseInterruptService (KINTERRUPT 81964008)
b1:    81be423c ACPI!ACPIInterruptServiceRoutine (KINTERRUPT 81be4200)
b2:    81795bec serial!SerialCIsrSw (KINTERRUPT 81795bb0)
b4:    818765d4 NDIS!ndisMIsr (KINTERRUPT 81876598)
c1:    806e6ac0 hal!HalpBroadcastCallService
d1:    806e5e54 hal!HalpClockInterrupt
e1:    806e7048 hal!HalpIpiHandler
e3:    806e6dac hal!HalpLocalApicErrorService
fd:    806e75a8 hal!HalpProfileInterrupt
fe:    806e7748 hal!HalpPerfInterrupt&lt;/pre&gt;

&lt;p&gt;單純的 !idt 只會輸出 ntoskrnl.exe 之外的 interrupt handler ，若想看到全部 IDT 項目，則須加上 -a：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;!idt -a&lt;/pre&gt;

&lt;h1&gt;More&lt;/h1&gt;

&lt;pre&gt;0: kd&amp;gt; !idt

Dumping IDT:

37:    806e6864 hal!PicSpuriousService37
3d:    806e7e2c hal!HalpApcInterrupt
41:    806e7c88 hal!HalpDispatchInterrupt
50:    806e693c hal!HalpApicRebootService
&lt;font color="#ff0000"&gt;&lt;font color="#0080ff"&gt;62&lt;/font&gt;&lt;font color="#000000"&gt;:&lt;/font&gt;    81bbe6f4 &lt;font color="#008000"&gt;atapi!IdePortInterrupt&lt;/font&gt; &lt;/font&gt;&lt;font color="#000000"&gt;(&lt;font color="#8080ff"&gt;KINTERRUPT 81bbe6b8&lt;/font&gt;)&lt;/font&gt;
63:    8191a974 USBPORT!USBPORT_InterruptService (KINTERRUPT 8191a938)
             portcls!CKsShellRequestor::`scalar deleting destructor'+0x26 (KINTERRUPT 8197cbb0)
73:    81962bec USBPORT!USBPORT_InterruptService (KINTERRUPT 81962bb0)&lt;/pre&gt;

&lt;p&gt;一般的情況下，!idt 已經給予足夠的資訊了，以上面的 IDE 介面來說：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;它的 interrupt number 是 &lt;font color="#0080ff"&gt;62&lt;/font&gt; 、 &lt;/li&gt;

  &lt;li&gt;ISR 是位於 &lt;font color="#008000"&gt;atapi&lt;/font&gt; module 的 &lt;font color="#008000"&gt;IdePortInterrupt&lt;/font&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;不過好奇心驅使，可以發現：當去查詢 &lt;font color="#008000"&gt;atapi!IdePortInterrupt&lt;/font&gt; 的位置時，卻不是 &lt;font color="#ff0000"&gt;0x81bbe6f4&lt;/font&gt; 、也不是 &lt;font color="#8080ff"&gt;0x81bbe6b8&lt;/font&gt;。&lt;/p&gt;

&lt;pre&gt;0: kd&amp;gt; x atapi!IdePortInterrupt
&lt;font color="#0000ff"&gt;f980467e&lt;/font&gt; atapi!IdePortInterrupt = &lt;no information type&gt;&lt;/pre&gt;

&lt;p&gt;而是 &lt;font color="#0000ff"&gt;0xf980467e&lt;/font&gt; ，加上一個 IDT entry 竟然有這麼多 addresses ，真是詭異。所以我們可以懷疑一下，!idt 這個指令的輸出是經過&lt;em&gt;加工&lt;/em&gt;的。不過必須找到一些更基礎的資訊來支持這個懷疑。在 x86 處理器的 protected mode 中， IDT 是由 IDTR （&lt;u&gt;I&lt;/u&gt;nterrupt &lt;u&gt;D&lt;/u&gt;escriptor &lt;u&gt;T&lt;/u&gt;able &lt;u&gt;R&lt;/u&gt;egister）所紀錄，所以來看看 registers 的狀況如何：&lt;/p&gt;

&lt;pre&gt;0: kd&amp;gt; &lt;font color="#0080ff"&gt;r&lt;/font&gt;
eax=00000001 ebx=ffdff980 ecx=80554780 edx=000003f8 esi=00000003 edi=19d73a7c
eip=8052c5ec esp=805523b0 ebp=805523c0 iopl=0         nv up ei pl nz na po nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000202
nt!RtlpBreakWithStatusInstruction:
8052c5ec cc              int     3&lt;/pre&gt;

&lt;p&gt;什麼？沒有 IDTR ，原來要打 r &lt;font color="#800080"&gt;idtr&lt;/font&gt;：&lt;/p&gt;

&lt;pre&gt;0: kd&amp;gt; &lt;font color="#0080ff"&gt;r&lt;/font&gt; &lt;font color="#800080"&gt;idtr&lt;/font&gt;
idtr=&lt;font color="#ff8080"&gt;8003f400&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;知道 IDT 的位置後，必須算出適當的位移量來找到 &lt;font color="#ff0000"&gt;atapi!IdePortInterrupt&lt;/font&gt; ，參考一下 Intel 的文件：&lt;a href="http://www.intel.com/Assets/PDF/manual/253668.pdf" target="_blank"&gt;Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3A: System Programming Guide&lt;/a&gt; 5.10 可以知道 IDT entry —— interrupt gate 的格式：&lt;/p&gt;

&lt;p align="center"&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/S27jsDbbvFI/AAAAAAAAAnk/v7UPdIi0pNk/s1600-h/InterruptObject06%5B10%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="InterruptObject06" border="0" alt="InterruptObject06" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/S27js6jTbZI/AAAAAAAAAno/-PWjEX-YSnk/InterruptObject06_thumb%5B8%5D.jpg?imgmax=800" width="640" height="221" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;所以，&lt;font color="#ff0000"&gt;atapi!IdePortInterrupt&lt;/font&gt; 等於：&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/S27jtTTvQvI/AAAAAAAAAns/kcDs-9Qu9jI/s1600-h/image%5B5%5D.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/S27juOazzyI/AAAAAAAAAnw/xh8i1crwbtM/image_thumb%5B3%5D.png?imgmax=800" width="360" height="73" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;pre&gt;0: kd&amp;gt; dd &lt;font color="#ff8080"&gt;8003f400&lt;/font&gt;+0x8*0x62
8003f710  0008&lt;font color="#ff0000"&gt;e6f4&lt;/font&gt; &lt;font color="#ff0000"&gt;81bb&lt;/font&gt;8e00 0008a974 81918e00
8003f720  00081d28 80548e00 00081d32 80548e00
8003f730  00081d3c 80548e00 00081d46 80548e00&lt;/pre&gt;

&lt;p&gt;跟 IDT Entry 第一個 address 是符合的，所以可以確定它是 interrupt handler 的 entry point：&lt;/p&gt;

&lt;pre&gt;&lt;font color="#0080ff"&gt;62&lt;/font&gt;:    &lt;font color="#ff0000"&gt;81bbe6f4&lt;/font&gt; &lt;font color="#008000"&gt;atapi!IdePortInterrupt&lt;/font&gt; &lt;font color="#0080ff"&gt;(&lt;font color="#8080ff"&gt;KINTERRUPT 81bbe6b8&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;)&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;那麼該怎麼從這 &lt;font color="#800000"&gt;&lt;font color="#ff0000"&gt;0x81bbe6f4&lt;/font&gt; &lt;/font&gt;entry point 到 &lt;font color="#008000"&gt;atapi!IdePortInterrupt&lt;/font&gt;&amp;#160; 去執行呢？線索就在 &lt;font color="#8080ff"&gt;KINTERRUPT 81bbe6b8&lt;/font&gt; 上， Windows 透過 interrupt object 來管理系統上的 interrupts ，driver programmers 必須向 interrrupt object 註冊自己的 ISR ，那麼 interrupt handling flow 才會有機會執行到這個 ISR 。&lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx" target="_blank"&gt;Windows Internals&lt;/a&gt; chapter 3 有針對 interrupt 作詳細的說明。透過 dt 指令可以看到存放在 &lt;font color="#8080ff"&gt;0x81bbe6b8&lt;/font&gt; 的 kinterrupt 變數。&lt;/p&gt;

&lt;pre&gt;0: kd&amp;gt; dt nt!_kinterrupt &lt;font color="#8080ff"&gt;81bbe6b8&lt;/font&gt;
   +0x000 Type             : 22
   +0x002 Size             : 484
   +0x004 InterruptListEntry : _LIST_ENTRY [ 0x81bbe6bc - 0x81bbe6bc ]
   +0x00c ServiceRoutine   : 0xf980467e     unsigned char  atapi!IdePortInterrupt+0
   +0x010 ServiceContext   : 0x81bbd030 
   +0x014 SpinLock         : 0
   +0x018 TickCount        : 0xffffffff
   +0x01c ActualLock       : 0x81bbe91c  -&amp;gt; 0
   +0x020 DispatchAddress  : 0x80546660     void  nt!KiInterruptDispatch+0
   +0x024 Vector           : 0x162
   +0x028 Irql             : 0x5 ''
   +0x029 SynchronizeIrql  : 0x5 ''
   +0x02a FloatingSave     : 0 ''
   +0x02b Connected        : 0x1 ''
   +0x02c Number           : 0 ''
   +0x02d ShareVector      : 0 ''
   +0x030 Mode             : 1 ( Latched )
   +0x034 ServiceCount     : 0
   +0x038 DispatchCount    : 0xffffffff
   &lt;font color="#ff0000"&gt;+0x03c DispatchCode     : [106] 0x56535554&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;注意到沒有？放在 nt!_kinterrupt+0x03c 位置的 &lt;font color="#ff0000"&gt;DispatchCode&lt;/font&gt; 其實就是 IDT Eetry。&lt;/p&gt;

&lt;pre&gt;0: kd&amp;gt; .formats &lt;font color="#8080ff"&gt;0x81bbe6b8&lt;/font&gt;+&lt;strong&gt;&lt;font color="#ff0000"&gt;0x03c&lt;/font&gt;&lt;/strong&gt;
Evaluate expression:
  Hex:     &lt;font color="#ff0000"&gt;81bbe6f4&lt;/font&gt;
  Decimal: -2118392076
  Octal:   20156763364
  Binary:  10000001 10111011 11100110 11110100
  Chars:   ....
  Time:    ***** Invalid
  Float:   low -6.90244e-038 high -1.#QNAN
  Double:  -1.#QNAN&lt;/pre&gt;

&lt;p&gt;既然確定了&lt;font color="#ff0000"&gt; 0x56535554&lt;/font&gt; 就是 entry point ，那麼可以反組譯一下 DispatchCode 來確定是否會執行到 &lt;font color="#008000"&gt;atapi!IdePortInterrupt&lt;/font&gt; ：&lt;/p&gt;

&lt;pre&gt;0: kd&amp;gt; u &lt;font color="#ff0000"&gt;81bbe6f4&lt;/font&gt; 81bbe6f4+0x106*0x4
&lt;font color="#008080"&gt;; Setup Trap Frame&lt;/font&gt;
81bbe6f4 54              push    esp
81bbe6f5 55              push    ebp
81bbe6f6 53              push    ebx
81bbe6f7 56              push    esi
81bbe6f8 57              push    edi
81bbe6f9 83ec54          sub     esp,54h
81bbe6fc 8bec            mov     ebp,esp
81bbe6fe 89442444        mov     dword ptr [esp+44h],eax
81bbe702 894c2440        mov     dword ptr [esp+40h],ecx
81bbe706 8954243c        mov     dword ptr [esp+3Ch],edx
81bbe70a f744247000000200 test    dword ptr [esp+70h],20000h
81bbe712 0f852b010000    jne     81bbe843
81bbe718 66837c246c08    cmp     word ptr [esp+6Ch],8
81bbe71e 7423            je      81bbe743
81bbe720 8c642450        mov     word ptr [esp+50h],fs
81bbe724 8c5c2438        mov     word ptr [esp+38h],ds
81bbe728 8c442434        mov     word ptr [esp+34h],es
81bbe72c 8c6c2430        mov     word ptr [esp+30h],gs
81bbe730 bb30000000      mov     ebx,30h
81bbe735 b823000000      mov     eax,23h
81bbe73a 668ee3          mov     fs,bx
81bbe73d 668ed8          mov     ds,ax
81bbe740 668ec0          mov     es,ax
81bbe743 648b1d00000000  mov     ebx,dword ptr fs:[0]
81bbe74a 64c70500000000ffffffff mov dword ptr fs:[0],0FFFFFFFFh
81bbe755 895c244c        mov     dword ptr [esp+4Ch],ebx
81bbe759 81fc00000100    cmp     esp,10000h
81bbe75f 0f82b6000000    jb      81bbe81b
81bbe765 c744246400000000 mov     dword ptr [esp+64h],0
81bbe76d fc              cld
81bbe76e 8b5d60          mov     ebx,dword ptr [ebp+60h]
81bbe771 8b7d68          mov     edi,dword ptr [ebp+68h]
81bbe774 89550c          mov     dword ptr [ebp+0Ch],edx
81bbe777 c74508000ddbba  mov     dword ptr [ebp+8],0BADB0D00h
81bbe77e 895d00          mov     dword ptr [ebp],ebx
81bbe781 897d04          mov     dword ptr [ebp+4],edi
81bbe784 64f60550000000ff test    byte ptr fs:[50h],0FFh
81bbe78c 750d            jne     81bbe79b
&lt;font color="#008080"&gt;; Pass KInterrupt object to KiInterruptDispatch&lt;/font&gt;
81bbe78e bfb8e6bb81      mov     edi,&lt;font color="#ff0000"&gt;81BBE6B8h &lt;/font&gt;&lt;font color="#008080"&gt;; 0x81bbe6b8 是我們的 interrupt object&lt;/font&gt;
81bbe793 e9c87e98fe      jmp     &lt;font color="#0000ff"&gt;nt!KiInterruptDispatch (80546660)&lt;/font&gt;&lt;font color="#008080"&gt;; 0x80546660 interrupt object 中的 DispatchAddress 一欄&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;如果我們再追進 nt!KiInterruptDispatch ：&lt;/p&gt;

&lt;pre&gt;0: kd&amp;gt; u nt!KiInterruptDispatch L50
nt!KiInterruptDispatch:
80546660 64ff05c4050000  inc     dword ptr fs:[5C4h]
80546667 8bec            mov     ebp,esp
80546669 8b4724          mov     eax,dword ptr [edi+24h]
8054666c 8b4f29          mov     ecx,dword ptr [edi+29h]
8054666f 50              push    eax
80546670 83ec04          sub     esp,4
80546673 54              push    esp
80546674 50              push    eax
80546675 51              push    ecx
80546676 ff1590904d80    call    dword ptr [nt!_imp__HalBeginSystemInterrupt (804d9090)]
8054667c 0bc0            or      eax,eax
8054667e 7440            je      nt!KiInterruptDispatch+0x60 (805466c0)
80546680 83ec0c          sub     esp,0Ch
80546683 833d6c56568000  cmp     dword ptr [nt!PPerfGlobalGroupMask (8056566c)],0
8054668a c745f400000000  mov     dword ptr [ebp-0Ch],0
80546691 7541            jne     nt!KiInterruptDispatch+0x74 (805466d4)
80546693 8b771c          mov     esi,dword ptr [edi+1Ch]
80546696 f00fba2e00      lock bts dword ptr [esi],0
8054669b 722b            jb      nt!KiInterruptDispatch+0x68 (805466c8)
8054669d 8b4710          mov     eax,dword ptr [edi+10h]
805466a0 50              push    eax
805466a1 57              push    edi
&lt;font color="#008080"&gt;; 注意到了嗎？di 是 interrupt ojbect； edi+0Ch 是欄位 ServiceRoutine 也就是 0xf980467e atapi!IdePortInterrupt+0&lt;/font&gt;
805466a2 ff570c          &lt;font color="#ff0000"&gt;call    dword ptr [edi+0Ch]&lt;/font&gt; &lt;/pre&gt;

&lt;p&gt;終於，水落石出了！最後用 interrupt object 做一個總結：&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/S27jv00vyCI/AAAAAAAAAn0/Z1JBS5RvkE8/s1600-h/image%5B22%5D.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/S27jx5aWlRI/AAAAAAAAAn8/Xfxz3GDO00Q/image_thumb%5B14%5D.png?imgmax=800" width="640" height="429" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;當 interrupt 發生時，CPU 根據 &lt;font color="#0080ff"&gt;interrupt number&lt;/font&gt; 到 IDT 描述找到對應的 &lt;font color="#ff0000"&gt;DispatchCode&lt;/font&gt;&lt;font color="#000000"&gt;；&lt;/font&gt; &lt;/li&gt;

  &lt;li&gt;&lt;font color="#ff0000"&gt;DispatchCode&lt;/font&gt; 產生 trap frame ，然後呼叫對應的 &lt;font color="#0000ff"&gt;kernel interrupt handler&lt;/font&gt; （nt!KiInterruptDispatch），並將 &lt;font color="#8080ff"&gt;interrupt object&lt;/font&gt; 當作參數傳入&lt;font color="#000000"&gt;；&lt;/font&gt; &lt;/li&gt;

  &lt;li&gt;&lt;font color="#0000ff"&gt;Kernel interrupt handler&lt;/font&gt; 轉而呼叫對應的 &lt;font color="#008000"&gt;ISR&lt;/font&gt; 。 &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;那 !idt 輸出的格式就是：&lt;/p&gt;

&lt;p&gt;&lt;font color="#0080ff"&gt;Interrupt Number&lt;/font&gt;: &lt;font color="#ff0000"&gt;IDT Entry Code&lt;/font&gt;&amp;#160;&lt;font color="#008000"&gt;Kernel/User Defined ISR&lt;/font&gt; &lt;font color="#8080ff"&gt;(Corresponding interrupt object address)&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font color="#000000"&gt;是吧！再看一次：&lt;/font&gt;&lt;/p&gt;

&lt;pre&gt;0: kd&amp;gt; !idt

Dumping IDT:

37:    806e6864 hal!PicSpuriousService37
3d:    806e7e2c hal!HalpApcInterrupt
41:    806e7c88 hal!HalpDispatchInterrupt
50:    806e693c hal!HalpApicRebootService
&lt;font color="#0080ff"&gt;62&lt;/font&gt;:    &lt;font color="#ff0000"&gt;81bbe6f4&lt;/font&gt; &lt;font color="#008000"&gt;atapi!IdePortInterrupt&lt;/font&gt; (&lt;font color="#8080ff"&gt;KINTERRUPT 81bbe6b8&lt;/font&gt;)
63:    8191a974 USBPORT!USBPORT_InterruptService (KINTERRUPT 8191a938)
             portcls!CKsShellRequestor::`scalar deleting destructor'+0x26 (KINTERRUPT 8197cbb0)
73:    81962bec USBPORT!USBPORT_InterruptService (KINTERRUPT 81962bb0)
82:    81bd4bec atapi!IdePortInterrupt (KINTERRUPT 81bd4bb0)
83:    81be1ae4 SCSIPORT!ScsiPortInterrupt (KINTERRUPT 81be1aa8)
93:    81965204 i8042prt!I8042KeyboardInterruptService (KINTERRUPT 819651c8)
a3:    81964044 i8042prt!I8042MouseInterruptService (KINTERRUPT 81964008)
b1:    81be423c ACPI!ACPIInterruptServiceRoutine (KINTERRUPT 81be4200)
b2:    81795bec serial!SerialCIsrSw (KINTERRUPT 81795bb0)
b4:    818765d4 NDIS!ndisMIsr (KINTERRUPT 81876598)
c1:    806e6ac0 hal!HalpBroadcastCallService
d1:    806e5e54 hal!HalpClockInterrupt
e1:    806e7048 hal!HalpIpiHandler
e3:    806e6dac hal!HalpLocalApicErrorService
fd:    806e75a8 hal!HalpProfileInterrupt
fe:    806e7748 hal!HalpPerfInterrupt&lt;/pre&gt;

&lt;p&gt;: )&lt;/p&gt;

&lt;h1&gt;相關閱讀&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href="http://keikoblog.blogspot.com/2009/03/windows-debugging-kernel-debugging-with.html"&gt;Windows Debugging – Kernel Debugging with WinDbg and VMWare&lt;/a&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;Reference&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx" target="_blank"&gt;Windows Internals&lt;/a&gt; chapter 3 &lt;/li&gt;

  &lt;li&gt;Intel® 64 and IA-32 Architectures Software Developer's Manuals: &lt;a title="http://www.intel.com/products/processor/manuals/" href="http://www.intel.com/products/processor/manuals/"&gt;http://www.intel.com/products/processor/manuals/&lt;/a&gt; &lt;/li&gt;
&lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-1919850990521399843?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/1919850990521399843/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=1919850990521399843' title='6 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/1919850990521399843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/1919850990521399843'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2010/02/interrupt-handling-in-windows-part-1.html' title='Interrupt Handling in Windows —— part 1: Using WinDbg'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_2ZMoTkLFVu8/S27js6jTbZI/AAAAAAAAAno/-PWjEX-YSnk/s72-c/InterruptObject06_thumb%5B8%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-6673413356021698082</id><published>2010-01-12T00:01:00.001+08:00</published><updated>2010-01-12T00:24:38.558+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C++0x'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><title type='text'>C++ and Beyond</title><content type='html'>&lt;p&gt;大師們要開講了～&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.aristeia.com/" target="_blank"&gt;Scott Meyers&lt;/a&gt;, &lt;a href="http://herbsutter.wordpress.com/" target="_blank"&gt;Herb Sutter&lt;/a&gt;, &lt;a href="http://erdani.com/" target="_blank"&gt;Andrei Alexandrescu&lt;/a&gt;, Seattle area, summer 2010!!! &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;This summer, Scott, Herb, and Andrei will host an intensive three-day technical event focusing on … Attendance will be limited to &lt;em&gt;&lt;font color="#0080ff"&gt;provide face time and direct interaction of attendees with speakers&lt;/font&gt;&lt;/em&gt;.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;em&gt;&lt;a href="http://cppandbeyond.com/" target="_blank"&gt;C++ and Beyond: 2010&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;C++ and Beyond&lt;/em&gt; will take place near Seattle, but you get to decide when it will take place. Please let us know what you think.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;看了一下可以選的時段有：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;June 21-23, 2010 &lt;/li&gt;    &lt;li&gt;August 16-18, 2010 &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;題目可以選：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Concurrency and parallelism - scalability and throughput &lt;/li&gt;    &lt;li&gt;Concurrency and parallelism - avoiding races and deadlocks &lt;/li&gt;    &lt;li&gt;Concurrency and parallelism - application responsiveness &lt;/li&gt;    &lt;li&gt;New programming languages (e.g., D, Go) &lt;/li&gt;    &lt;li&gt;High performance, maximizing execution speed &lt;/li&gt;    &lt;li&gt;C++0x lambdas &lt;/li&gt;    &lt;li&gt;What's new in C++0x (and starting to be available in compilers) &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;哇，好想去看看～&lt;/p&gt;  &lt;p&gt;如果有興趣的話，可以去&lt;a href="http://cppandbeyond.com/2010/01/07/vote-for-the-date/" target="_blank"&gt;投票&lt;/a&gt;～&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-6673413356021698082?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/6673413356021698082/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=6673413356021698082' title='3 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/6673413356021698082'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/6673413356021698082'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2010/01/c-and-beyond.html' title='C++ and Beyond'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-3884892116544606333</id><published>2009-12-23T00:12:00.001+08:00</published><updated>2009-12-23T00:27:13.003+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>程式設計師</title><content type='html'>&lt;h2&gt;Document&lt;/h2&gt;  &lt;blockquote&gt;   &lt;p&gt;出來跑的，總是要還～&lt;/p&gt; &lt;/blockquote&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;Design Review&lt;/h2&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;Architect&lt;/strong&gt;：加油，好嗎？&lt;/p&gt; &lt;/blockquote&gt;  &lt;h2&gt;Coding&lt;/h2&gt;  &lt;blockquote&gt;   &lt;p&gt;寫 Code 是一時的，maintain 是一世的…&lt;/p&gt; &lt;/blockquote&gt;  &lt;h2&gt;Bug&lt;/h2&gt;  &lt;blockquote&gt;   &lt;p&gt;We are extremely fortunate not to know precisely that kind of &lt;em&gt;&lt;strong&gt;bug&lt;/strong&gt;&lt;/em&gt; we live in.&lt;/p&gt; &lt;/blockquote&gt;  &lt;h2&gt;Code Review&lt;/h2&gt;  &lt;blockquote&gt;   &lt;p&gt;曾經有一段複製來的 code 擺在我的面前，      &lt;br /&gt;但是我沒有 refactor ，       &lt;br /&gt;直到新 feature 來的時候才後悔莫及，       &lt;br /&gt;如果上天能再給我一次機會的話，       &lt;br /&gt;我還是會 copy-and-paste，       &lt;br /&gt;如果非要在這分 code 上修改的話，       &lt;br /&gt;我希望是…下一版…&lt;/p&gt; &lt;/blockquote&gt;  &lt;h2&gt;Performance&lt;/h2&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;客戶&lt;/strong&gt;：出來面對～&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-3884892116544606333?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/3884892116544606333/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=3884892116544606333' title='6 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3884892116544606333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3884892116544606333'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/12/blog-post_23.html' title='程式設計師'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-3760565782261899044</id><published>2009-12-20T21:49:00.001+08:00</published><updated>2009-12-20T21:49:41.950+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Book'/><title type='text'>逛書店</title><content type='html'>&lt;p&gt;趁著寒流發威，跑去重慶南路逛書店，心想這種冷天氣，應該比較少人出門，沒想到如意算盤打錯，書店滿滿都是人，還看到很多媽媽特地把小孩帶來書店消磨時間，好吧，我以我們是個書香社會為榮（那出版社怎麼一直倒?!）&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/Sy4rbMSpwuI/AAAAAAAAAmc/VGDsKjtMWks/s1600-h/Image.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="貨幣崛起" border="0" alt="貨幣崛起" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/Sy4rbmJWcKI/AAAAAAAAAmg/hl99QFi95S0/Image.jpg?imgmax=800" width="174" height="244" /&gt;&lt;/a&gt; &lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/Sy4rclA1rjI/AAAAAAAAAmk/nea2WrPL1fQ/s1600-h/Computer%20Architecture%5B2%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Computer Architecture" border="0" alt="Computer Architecture" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/Sy4rdERRPPI/AAAAAAAAAmo/L_pwlBclcmE/Computer%20Architecture_thumb.jpg?imgmax=800" width="199" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;一本娛樂用，一本自強不息～&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-3760565782261899044?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/3760565782261899044/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=3760565782261899044' title='3 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3760565782261899044'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3760565782261899044'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/12/blog-post.html' title='逛書店'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_2ZMoTkLFVu8/Sy4rbmJWcKI/AAAAAAAAAmg/hl99QFi95S0/s72-c/Image.jpg?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-582617404168731696</id><published>2009-12-05T01:09:00.001+08:00</published><updated>2009-12-05T01:09:17.745+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>Weekly Report (20091123 ~ 20091127)</title><content type='html'>&lt;p&gt;每到星期五或星期一，我都會用 outlook 寫下跟這篇文章有著極類似標題的信給主管和同事們，不過同樣內容寫在這邊就會 &lt;a href="http://en.wikipedia.org/wiki/Considered_harmful" target="_blank"&gt;considered harmful&lt;/a&gt;～（這是工程師的冷笑話吧！）&lt;/p&gt;  &lt;hr /&gt;  &lt;p&gt;星期二 regular meeting 後，一直感到頭暈，龜毛地我在位子與廁所來回走了四次，爾後才決定要請假回家，心中一直懸在一份即將要截止的 design 上，這是某種程度的任重道遠嗎？還是不見棺材不掉淚？&lt;/p&gt;  &lt;p&gt;往診所的路上，寒風颼颼，腦袋倒是熱轉不停，想起有人曾說程式設計師都很樂觀，不確定我是不是這樣，但上禮拜著手一份 POC 程式，打從星期一下手之際，就覺得快做完，當晚下班時審視一下，雖不中亦不遠矣！樂觀持續到星期四，連帶延誤 design 的進度…&lt;/p&gt;  &lt;p&gt;咳咳，帶著深深地罪惡感走進問診室，醫生診斷後，說：快感冒了，但是還沒感冒，喉嚨有發炎，趕快吃個藥回去睡覺，對了，這不是流感！走出聽診室，總覺得話中有話，我看起來很像是會主動要求施打流感疫苗的人嗎？&lt;/p&gt;  &lt;hr /&gt;  &lt;p&gt;POC 的驗證是大陸的同事負責，這禮拜有很多跟他們講電話的機會。原先覺得都是中文應該很好溝通，沒想到電話那頭，講得又快又有口音，加上一些英文單字，發現不太能習慣，倒是他們似乎很快就習慣我們！official build 聽成 official way、checked build 聽成七個 build … 這一定是 VoIP 掉封包了…&lt;/p&gt;  &lt;hr /&gt;  &lt;p&gt;星期五晚上的公司總有一股特別的氣氛，彷彿阿宅都不阿宅了，每個人都有行程，好像再忙，都不能禮拜五加班啊！不過逆向操作的好處就是有股安定感，沒有嘈雜聲、步調也慢了下來，有種喝販賣機咖啡都像是在左岸咖啡館、design doc 也變文學鉅作了…&lt;/p&gt;  &lt;p&gt;公車站牌前，過了好幾部新店客運的公車，我都選擇等下一班，明明就十點了，公車上的人卻異常的多，從他們的表情看來，不太像 happy 完後要回家，原來我剛剛並不孤單！等公車總是會胡思亂想：可以的話，希望可以永遠保持清醒！可是為了什麼，我們要保持清醒呢？為了做更多的工作？為了有更多的時間做讓自己快樂的事？什麼是讓自己快樂的事？什麼是人生的意義？渾渾噩噩為什麼就不好？因為渾渾噩噩後，我們會後悔？可是能接受自己大半輩子渾渾噩噩的人，最後又怎麼會後悔呢？&lt;/p&gt;  &lt;hr /&gt;  &lt;p&gt;上個禮拜是到部門一年，老闆很 high 地跟我說：開口，你破冬了唷！&lt;/p&gt;  &lt;p&gt;我茫茫然然的，總覺得最近有點沒勁～&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-582617404168731696?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/582617404168731696/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=582617404168731696' title='5 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/582617404168731696'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/582617404168731696'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/12/weekly-report-20091123-20091127.html' title='Weekly Report (20091123 ~ 20091127)'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-1039122120435177186</id><published>2009-11-27T23:08:00.001+08:00</published><updated>2009-11-27T23:11:48.194+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><title type='text'>Invalid Parameter Handler and Security Enhancements in the CRT</title><content type='html'>&lt;p&gt;在 VC++ 的 CRT 中，除了標準的 CRT 之外，Microsoft 也加入安全性的檢查和報錯機制，許多原有的 functions 都被加上 &lt;em&gt;&lt;font color="#0080ff"&gt;_s&lt;/font&gt;&lt;/em&gt; 的後贅字。舉例來說：strcpy_s(), wcscpy_s(), _mbscpy_s() 各別是 strcpy(), wcscpy(), mbscpy() 的 security enhanced 版。這些 Security enhancement 的重點在於：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Parameter validation &lt;/li&gt;    &lt;li&gt;Sized buffers &lt;/li&gt;    &lt;li&gt;Null termination &lt;/li&gt;    &lt;li&gt;Enhanced error reporting &lt;/li&gt;    &lt;li&gt;Filesystem security &lt;/li&gt;    &lt;li&gt;Windows security &lt;/li&gt;    &lt;li&gt;Format string syntax checking &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;針對上述項目的檢查與 enforcement ，security-enhanced CRT 一旦發現問題，是不會嘗試去修正或繞過的，錯了就是錯了，舉例來說：&lt;a href="http://msdn.microsoft.com/zh-tw/library/td1esda9%28VS.80%29.aspx" target="_blank"&gt;wcscpy_s()&lt;/a&gt; 在 copy 記憶體時，一旦發現 destination buffer 比 source buffer 小，它並不會自動進行 truncation ，參考下面這個從 MSDN 來的例子：&lt;/p&gt;  &lt;pre class="brush: cpp;"&gt;errno_t wcscpy_s(
   wchar_t *strDestination,
   size_t sizeInWords,
   const wchar_t *strSource 
);&lt;/pre&gt;

&lt;div align="center"&gt;
  &lt;table border="1" cellspacing="0" cellpadding="2" width="620" align="center"&gt;&lt;tbody&gt;
      &lt;tr&gt;
        &lt;td width="114" align="center"&gt;strDestination&lt;/td&gt;

        &lt;td width="163" align="center"&gt;sizeInBytes, sizeInWords&lt;/td&gt;

        &lt;td width="82" align="center"&gt;strSource&lt;/td&gt;

        &lt;td width="99" align="center"&gt;Return value &lt;/td&gt;

        &lt;td width="160" align="center"&gt;Contents of strDestination&lt;/td&gt;
      &lt;/tr&gt;

      &lt;tr&gt;
        &lt;td width="116" align="center"&gt;&lt;b&gt;NULL&lt;/b&gt;&lt;/td&gt;

        &lt;td width="160" align="center"&gt;any&lt;/td&gt;

        &lt;td width="84" align="center"&gt;any&lt;/td&gt;

        &lt;td width="97" align="center"&gt;&lt;b&gt;EINVAL&lt;/b&gt;&lt;/td&gt;

        &lt;td width="159" align="center"&gt;not modified&lt;/td&gt;
      &lt;/tr&gt;

      &lt;tr&gt;
        &lt;td width="117" align="center"&gt;any&lt;/td&gt;

        &lt;td width="158" align="center"&gt;any&lt;/td&gt;

        &lt;td width="86" align="center"&gt;&lt;b&gt;NULL&lt;/b&gt;&lt;/td&gt;

        &lt;td width="97" align="center"&gt;&lt;b&gt;EINVAL&lt;/b&gt;&lt;/td&gt;

        &lt;td width="159" align="center"&gt;not modified&lt;/td&gt;
      &lt;/tr&gt;

      &lt;tr&gt;
        &lt;td width="118" align="center"&gt;any&lt;/td&gt;

        &lt;td width="156" align="center"&gt;0, or too small&lt;/td&gt;

        &lt;td width="87" align="center"&gt;any&lt;/td&gt;

        &lt;td width="98" align="center"&gt;&lt;b&gt;ERANGE&lt;/b&gt;&lt;/td&gt;

        &lt;td width="160" align="center"&gt;not modified&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;從表中可以看到，一旦 destination 和 source 有不正確的配對，那麼就不會對 destination 進行動，自然也就沒有把字串 truncate 後複製過去的結果發生。因此如果 truncation 是期望的結局，那就必須改用 str&lt;font color="#0080ff"&gt;n&lt;/font&gt;cpy_s(), _str&lt;font color="#0080ff"&gt;n&lt;/font&gt;cpy_s_l(), wcs&lt;font color="#0080ff"&gt;n&lt;/font&gt;cpy_s(), _wcs&lt;font color="#0080ff"&gt;n&lt;/font&gt;cpy_s_l(), _mbs&lt;font color="#0080ff"&gt;n&lt;/font&gt;cpy_s(), _mbs&lt;font color="#0080ff"&gt;n&lt;/font&gt;cpy_s_l() 這類原本就有 truncate 語意的函式。所以了，引用一下 MSDN 總結：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;... the secure functions do not prevent or correct security errors; rather, they catch errors when they occur. They perform additional checks for error conditions, and in the case of an error, they invoke an error handler (see &lt;a href="http://msdn.microsoft.com/en-us/library/ksazx244.aspx"&gt;Parameter Validation&lt;/a&gt;).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;沒錯，security enhancement 強調的是參數使用前的檢查以及可錯誤發生後的處理，不是幫忙修正錯誤。&lt;/p&gt;

&lt;h1&gt;Parameter Validation&lt;/h1&gt;

&lt;p&gt;Parameter validation 機制會檢查傳入 _s functions 的參數，檢查包括：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Checking pointers for NULL &lt;/li&gt;

  &lt;li&gt;Checking that integers fall into a valid range &lt;/li&gt;

  &lt;li&gt;Checking that enumeration values are valid &lt;/li&gt;

  &lt;li&gt;Validate that the buffer is large enough before writing to it &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;當 CRT 發現 invalid parameter 時，它會呼叫 &lt;font color="#0080ff"&gt;&lt;em&gt;invalid parameter handler&lt;/em&gt;&lt;/font&gt; 來處理。 CRT 有預設的 invalid parameter handler ，它會呼叫 Dr. Watson 產生 dump ，然後跳出一個 Error report 程式詢問使用者要不要上傳這個錯誤報告。而程式若是以 debug mode 編譯，則是會跳出 assertion。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/Sw_rQ3oJBOI/AAAAAAAAAmA/rXDfefuzEZI/s1600-h/drwtsn32%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="drwtsn32" border="0" alt="drwtsn32" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/Sw_rSJkjLxI/AAAAAAAAAmE/0V_UcifKXVU/drwtsn32_thumb%5B2%5D.jpg?imgmax=800" width="355" height="461" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p align="center"&gt;Fig 1. Dr. Watson （不是這個&lt;a href="http://en.wikipedia.org/wiki/John_Watson_%28Sherlock_Holmes%29" target="_blank"&gt;華生&lt;/a&gt;？也不是&lt;a href="http://tw.ent.yimg.com/mpost/30/66/3066.jpg" target="_blank"&gt;裘德洛&lt;/a&gt;？）&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/Sw_rS4DWN4I/AAAAAAAAAmI/zlIujkA9tbU/s1600-h/WER%5B6%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="WER" border="0" alt="WER" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/Sw_rTTIs3jI/AAAAAAAAAmM/U2A8PfWzRfU/WER_thumb%5B4%5D.jpg?imgmax=800" width="423" height="257" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p align="center"&gt;Fig 2. Windows Error Reporting 對話方塊 &lt;/p&gt;

&lt;p align="center"&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/Sw_rUBQO79I/AAAAAAAAAmQ/LH2uK4D6hNY/s1600-h/Assertion%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Assertion" border="0" alt="Assertion" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/Sw_rU7vhNYI/AAAAAAAAAmU/x5w8HJz0C1o/Assertion_thumb%5B2%5D.jpg?imgmax=800" width="379" height="261" /&gt;&lt;/a&gt;Fig 3. Debug Mode 下跳出的 assertion failed 視窗&lt;/p&gt;

&lt;h1&gt;Where have all the Exceptions gone?&lt;/h1&gt;

&lt;pre class="brush: cpp;"&gt;const wchar_t*  src = L&amp;quot;Hello&amp;quot;;
wchar_t         dest[ 5 ];

__try {
    wcscpy_s( dest, _countof( dest ), src );
}
__except ( EXCEPTION_EXECUTE_HANDLER ) {
    // Error handle...
}&lt;/pre&gt;

&lt;p&gt;在某些程式裡頭會看到像上面那樣的片段程式碼，看起來似乎四平八穩：我們指定了 dest 和其大小，若是 src 長度超過了 dest ， wcscpy_s() 透過 exception 報錯，我們就可以透過 SEH 來處理。但程式一執行，ㄜ，好像 crash 了… 不過現在我們已經可以可能的問題是什麼：若是程式沒有置換過 invalid parameter handler ，那麼是丟不出 exception 的，程式的 crash 便是可預期的結果。&lt;/p&gt;

&lt;h1&gt;Install my own Invalid Parameter Handler&lt;/h1&gt;

&lt;pre class="brush: cpp;"&gt;/*!
 * \param[in] expression argument expression
 * \param[in] function   the name of the CRT function that received the invalid argument
 * \param[in] file       file name in the CRT source
 * \param[in] line       line in file
 * \param[in] pReserved  reserved
 */
void _invalid_parameter(
    const wchar_t* expression,
    const wchar_t* function, 
    const wchar_t* file, 
    unsigned int   line,
    uintptr_t      pReserved
);&lt;/pre&gt;

&lt;p&gt;上述是 invalid parameter handler 的 &lt;a href="http://msdn.microsoft.com/en-us/library/a9yf33zb.aspx" target="_blank"&gt;prototype&lt;/a&gt;。我們很容易仿造一個自己的，延續之前 wcscpy_s() 的例子，我們就可以實作一個會丟出 exception 的 handler：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;void myInvalidParameterHandler( const wchar_t* expression,
                                const wchar_t* function, 
                                const wchar_t* file, 
                                unsigned int line,
                                uintptr_t reserved )
{
    wcout &amp;lt;&amp;lt; L&amp;quot;expr:&amp;quot; &amp;lt;&amp;lt; expression &amp;lt;&amp;lt; endl
          &amp;lt;&amp;lt; L&amp;quot;func: &amp;quot; &amp;lt;&amp;lt; function &amp;lt;&amp;lt; endl
          &amp;lt;&amp;lt; L&amp;quot;file:&amp;quot; &amp;lt;&amp;lt; file &amp;lt;&amp;lt; endl
          &amp;lt;&amp;lt; L&amp;quot;line:&amp;quot; &amp;lt;&amp;lt; line &amp;lt;&amp;lt; endl;

    RaiseException( 0,          // exception code
                    0,          // continuable exception
                    0, NULL );  // no arguments
}&lt;/pre&gt;

&lt;p&gt;然後透過 &lt;a href="http://msdn.microsoft.com/en-us/library/a9yf33zb.aspx" target="_blank"&gt;_set_invalid_parameter_handler()&lt;/a&gt; 來註冊：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;wchar_t   dest[ 5 ];
const wchar_t*  src = L&amp;quot;Hello&amp;quot;;

_invalid_parameter_handler oldHandler = _set_invalid_parameter_handler( myInvalidParameterHandler );

_CrtSetReportMode( _CRT_ASSERT, 0 );

__try {
    wcscpy_s( dest, _countof( dest ), src );
}
__except ( EXCEPTION_EXECUTE_HANDLER ) {
    cerr &amp;lt;&amp;lt; &amp;quot;exception ... &amp;quot; &amp;lt;&amp;lt; GetExceptionCode() &amp;lt;&amp;lt; endl;
}&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/1y71x448%28VS.80%29.aspx" target="_blank"&gt;_CrtSetReportMode()&lt;/a&gt; 在這裡可以幫助 debug mode 下取消 assertion failed 視窗的跳出。如果對於 wcscpy_s() 的 errno_t 的 error code 念念不忘，則可以修改 SEH 的 filter expression 從 EXCEPTION_EXECUTE_HANDLE 到 EXCEPTION_CONTINUE_EXECUTION。&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;__try {
    errno_t e = wcscpy_s( dest, _countof( dest ), src );

    if ( EINVAL == e ) {
        // ...
    }
    else if ( ERANGE == e ){
        // ...
    }
}
__except ( EXCEPTION_CONTINUE_EXECUTION ) {
}&lt;/pre&gt;

&lt;p&gt;PS: EINVAL, ERANGE 這類 pre-defined error code 定義於 ERRNO.H 裡頭。&lt;/p&gt;

&lt;h1&gt;Reference&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;MSDN on Security Enhancements in the CRT: &lt;a title="http://msdn.microsoft.com/en-us/library/8ef0s5kh.aspx" href="http://msdn.microsoft.com/en-us/library/8ef0s5kh.aspx"&gt;http://msdn.microsoft.com/en-us/library/8ef0s5kh.aspx&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;MSDN on Parameter Validation: &lt;a title="http://msdn.microsoft.com/en-us/library/ksazx244.aspx" href="http://msdn.microsoft.com/en-us/library/ksazx244.aspx"&gt;http://msdn.microsoft.com/en-us/library/ksazx244.aspx&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;MSDN on _set_invalid_parameter_handler: &lt;a title="http://msdn.microsoft.com/en-us/library/a9yf33zb.aspx" href="http://msdn.microsoft.com/en-us/library/a9yf33zb.aspx"&gt;http://msdn.microsoft.com/en-us/library/a9yf33zb.aspx&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;MSDN on errno, _doserrno, _sys_errlist, and _sys_nerr: &lt;a title="http://msdn.microsoft.com/en-us/library/t3ayayh1.aspx" href="http://msdn.microsoft.com/en-us/library/t3ayayh1.aspx"&gt;http://msdn.microsoft.com/en-us/library/t3ayayh1.aspx&lt;/a&gt; &lt;/li&gt;
&lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-1039122120435177186?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/1039122120435177186/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=1039122120435177186' title='3 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/1039122120435177186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/1039122120435177186'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/11/invalid-parameter-handler-and-security.html' title='Invalid Parameter Handler and Security Enhancements in the CRT'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_2ZMoTkLFVu8/Sw_rSJkjLxI/AAAAAAAAAmE/0V_UcifKXVU/s72-c/drwtsn32_thumb%5B2%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-3693934926133284867</id><published>2009-10-13T12:19:00.001+08:00</published><updated>2009-10-13T12:19:40.074+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='研發替代役'/><title type='text'>賀，服役一週年！</title><content type='html'>&lt;p align="center"&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/StP_1jOvYHI/AAAAAAAAAl4/WZ5XxmUOEE8/s1600-h/TrendSchool2008%5B5%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="TrendSchool2008" border="0" alt="TrendSchool2008" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/StP_27eRsbI/AAAAAAAAAl8/V577rh65Nfs/TrendSchool2008_thumb%5B3%5D.jpg?imgmax=800" width="640" height="480" /&gt;&lt;/a&gt;&lt;font size="3" face="標楷體"&gt; 很高興認識大家，感謝過去一年所遇的貴人們，今後也要好好努力！&lt;/font&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-3693934926133284867?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/3693934926133284867/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=3693934926133284867' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3693934926133284867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3693934926133284867'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/10/blog-post.html' title='賀，服役一週年！'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_2ZMoTkLFVu8/StP_27eRsbI/AAAAAAAAAl8/V577rh65Nfs/s72-c/TrendSchool2008_thumb%5B3%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-2620789526084104640</id><published>2009-08-29T23:09:00.001+08:00</published><updated>2009-08-29T23:17:03.154+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Qt'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><title type='text'>Qt 為什麼要有 QScopedPointer 呢？</title><content type='html'>&lt;p&gt;不久前在 &lt;a href="http://labs.trolltech.com/blogs/" target="_blank"&gt;Qt Labs Blogs&lt;/a&gt; 上的一篇文章引起了我的注意，文章標題是：&lt;a href="http://labs.trolltech.com/blogs/2009/08/21/introducing-qscopedpointer/" target="_blank"&gt;Introducing QScopedPointer&lt;/a&gt; ，介紹了即將在 Qt 4.6 現身的新成員 — QScopedPointer ， Qt 4.6 的 preview 也已經放進了&lt;a href="http://doc.trolltech.com/4.6-snapshot/qscopedpointer.html" target="_blank"&gt;相關的文件&lt;/a&gt;。在 C++ 中使用 RAII 的手法是相當常見的，而且也納入標準之中的，或是 boost 也提供了 &lt;a href="http://www.boost.org/doc/libs/1_40_0/libs/smart_ptr/smart_ptr.htm" target="_blank"&gt;Smart Pointers library&lt;/a&gt; 。&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;為什麼 Qt 需要提供自己一套 Smart pointers 呢？&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Qt 背後的動機令我感到好奇，一如我在 &lt;a href="http://markmail.org/search/?q=QScopedPointer+boost#query:QScopedPointer%20boost%20+page:1+mid:ygj3wdoni2s2ydfk+state:results" target="_blank"&gt;KAutoPointer: a new autoptr class for QPointer&lt;/a&gt; 討論串上看到鄉民 Ingo Klöcker 說的：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;... Unfortunately, there appears to be quite some aversion against using &lt;strong&gt;boost&lt;/strong&gt;'s pointer template classes (a trivial compile time dependency) in KDE …&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;而的確，這也引起了一陣討論，下面收集了一些討論來瞭解一下：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;QT Labs Blogs:      &lt;ol&gt;       &lt;li&gt;&lt;a href="http://labs.trolltech.com/blogs/2009/08/21/introducing-qscopedpointer/" target="_blank"&gt;Introducing QScopedPointer&lt;/a&gt; &lt;/li&gt;        &lt;li&gt;&lt;a href="http://labs.trolltech.com/blogs/2009/08/25/count-with-me-how-many-smart-pointer-classes-does-qt-have/" target="_blank"&gt;Count with me: how many smart pointer classes does Qt have&lt;/a&gt; &lt;/li&gt;        &lt;li&gt;&lt;a href="http://labs.trolltech.com/blogs/2009/08/25/some-more-pointing/" target="_blank"&gt;Some more pointing&lt;/a&gt; &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt;    &lt;li&gt;Mailing list or news      &lt;ol&gt;       &lt;li&gt;&lt;a href="http://markmail.org/search/?q=QScopedPointer+boost#query:QScopedPointer%20boost%20+page:1+mid:3eiwn7cqwwklanl7+state:results" target="_blank"&gt;KAutoPointer: a new autoptr class for QPointer&lt;/a&gt; &lt;/li&gt;        &lt;li&gt;&lt;a href="http://www.osnews.com/comments/22050" target="_blank"&gt;OS news: Introducing QScopedPointer&lt;/a&gt; &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;題外話一下：有沒有興趣猜猜 Qt 提供了幾種 smart pointers 呢？在 &lt;a href="http://labs.trolltech.com/blogs/2009/08/25/count-with-me-how-many-smart-pointer-classes-does-qt-have/" target="_blank"&gt;Count with me: how many smart pointer classes does Qt have?&lt;/a&gt; 一文中列出了八種：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://doc.trolltech.com/4.5/qpointer.html"&gt;QPointer&lt;/a&gt; (4.0) &lt;/li&gt;    &lt;li&gt;&lt;a href="http://doc.trolltech.com/4.5/qshareddatapointer.html"&gt;QSharedDataPointer&lt;/a&gt; (4.0) &lt;/li&gt;    &lt;li&gt;&lt;a href="http://doc.trolltech.com/4.5/qexplicitlyshareddatapointer.html"&gt;QExplicitlySharedDataPointer&lt;/a&gt; (4.3/4.4) &lt;/li&gt;    &lt;li&gt;&lt;a href="http://qt.gitorious.org/qt/qt/blobs/master/src/xmlpatterns/utils/qautoptr_p.h#line72"&gt;QtPatternist::AutoPtr&lt;/a&gt; (internal class, 4.4) &lt;/li&gt;    &lt;li&gt;&lt;a href="http://doc.trolltech.com/4.6-snapshot/qsharedpointer.html"&gt;QSharedPointer&lt;/a&gt; (4.5) &lt;/li&gt;    &lt;li&gt;&lt;a href="http://doc.trolltech.com/4.6-snapshot/qweakpointer.html"&gt;QWeakPointer&lt;/a&gt; (4.5) &lt;/li&gt;    &lt;li&gt;&lt;a href="http://qt.gitorious.org/qt/qt/blobs/master/src/corelib/kernel/qguard_p.h#line61"&gt;QGuard&lt;/a&gt; (internal class, 4.6) &lt;/li&gt;    &lt;li&gt;&lt;a href="http://doc.trolltech.com/4.6-snapshot/qscopedpointer.html"&gt;QScopedPointer&lt;/a&gt; (4.6) &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;呵呵（或，科科），是不是很有趣呢？回到正題， &lt;a href="http://labs.trolltech.com/blogs/2009/08/25/count-with-me-how-many-smart-pointer-classes-does-qt-have/" target="_blank"&gt;Count with me: how many smart pointer classes does Qt have?&lt;/a&gt; 一文解釋了為什麼不採用既有的 scoped pointers：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;C++0x 尚未通過，其實作也只有在 GCC 4.3 之後以及 MSVC 2010 beta 中才有； &lt;/li&gt;    &lt;li&gt;TR1 的實作品不夠； &lt;/li&gt;    &lt;li&gt;Boost 呢，ㄜ，Qt 認為它是“un-Qt-ish” API，或者該說是“horrible API”，這句話其實是沒有惡意的，只是想說兩者的命名哲學不同。此外，Qt 與 KDE 對於 binary compatibility 有著嚴格、複雜的要求，若是採用 boost 實作會破壞這相容性。（如果有興趣，可以參考一下 KDE TechBase 上的一篇文章：&lt;a href="http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++" target="_blank"&gt;Policies/Binary Compatibility Issues With C++&lt;/a&gt; ，最近的貢獻者就是 Count with me … 一文的作者： &lt;a href="http://labs.trolltech.com/blogs/author/thiago/" target="_blank"&gt;Thiago Macieira&lt;/a&gt;。） &lt;/li&gt;    &lt;li&gt;Qt 還是希望握有 scoped pointer 的 knowledge。 &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;a href="http://www.osnews.com/comments/22050" target="_blank"&gt;&lt;font color="#494949"&gt;在我看來，&lt;/font&gt;&lt;/a&gt; Qt 期許自己成為一個成熟易用又跨平台的函式庫，它的支援環境可能沒有完整的標準 C++ 函式庫，又因為 C++ 缺乏統一的 ABI 支援，在某些應用上若沒有一些事先規範會讓事情發展到某種程度後窒礙難行，至於有多窒礙難行呢？我還不能說個所以然，因為自己沒有真的痛過，無法把那種罄竹難書講得感同身受 Orz …&lt;/p&gt;  &lt;p&gt;延伸閱讀：&lt;/p&gt;  &lt;p&gt;一些關於 ABI 、binary compatibility、modular mechanism 的討論：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Qt Labs Blogs: &lt;a href="http://labs.trolltech.com/blogs/2009/08/15/some-thoughts-on-calling-convention/"&gt;Some thoughts on calling convention&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Qt Labs Blogs: &lt;a href="http://labs.trolltech.com/blogs/2009/08/12/some-thoughts-on-binary-compatibility/"&gt;Some thoughts on binary compatibility&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.synesis.com.au/publishing/imperfect/cpp/" target="_blank"&gt;Imperfect C++: Part 2 - Surviving The Real World&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/Essential-COM-Don-Box/dp/0201634465" target="_blank"&gt;Essential COM: COM as a Better C++&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;C++0x 有過相關的討論：&lt;/li&gt;    &lt;ol&gt;     &lt;li&gt;&lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2073.pdf" target="_blank"&gt;Modules in C++&lt;/a&gt;&lt;/li&gt;      &lt;li&gt;&lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1496.html" target="_blank"&gt;Draft Proposal for Dynamic Libraries in C++&lt;/a&gt;&lt;/li&gt;      &lt;li&gt;不過&lt;a href="http://herbsutter.wordpress.com/2007/02/07/iso-c0x-complete-public-review-draft-in-october-2007/" target="_blank"&gt;被打槍&lt;/a&gt;了！&lt;/li&gt;   &lt;/ol&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-2620789526084104640?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/2620789526084104640/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=2620789526084104640' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/2620789526084104640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/2620789526084104640'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/08/qt-qscopedpointer.html' title='Qt 為什麼要有 QScopedPointer 呢？'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-3197499567705425848</id><published>2009-08-09T16:42:00.001+08:00</published><updated>2009-08-09T21:47:57.440+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Qt'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><title type='text'>Qt 4.5.2</title><content type='html'>&lt;p&gt;自從 Qt 被 Nokia 併購後，似乎越來越活耀(?!)，網站也改版了，不過以前的都會把 source code 版本直接放一個 link 出來，現在好像得去 &lt;a href="ftp://ftp.qtsoftware.com" target="_blank"&gt;ftp&lt;/a&gt; 下載，&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/Sn6LxZMDwuI/AAAAAAAAAkk/D38plNsCSwY/s1600-h/Qt_FTP%5B4%5D.jpg"&gt;&lt;img title="Qt_FTP" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="484" alt="Qt_FTP" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/Sn6LzW0ttPI/AAAAAAAAAko/vfvSlolwGZw/Qt_FTP_thumb%5B2%5D.jpg?imgmax=800" width="541" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h1&gt;編譯&lt;/h1&gt;  &lt;p&gt;官方的 binary 好像（不確定，我只試過 Qt SDK: Complete Development Environment 這包而已）只有給 mingw32 用的，如果想在 Windows 搭配 Visual C++ 使用，可以自己 compile ，請下載 &lt;a href="ftp://ftp.qtsoftware.com/qt/source/qt-win-opensource-src-4.5.2.zip" target="_blank"&gt;qt-win-opensource-src-4.5.2.zip&lt;/a&gt; 這個檔案，不要下載 &lt;a href="ftp://ftp.qtsoftware.com/qt/source/qt-all-opensource-src-4.5.2.tar.gz" target="_blank"&gt;qt-all-opensource-src-4.5.2.tar.gz&lt;/a&gt;，編譯時可能會有下面的錯誤：&lt;/p&gt;  &lt;pre class="brush: bash;"&gt;qscriptdebuggercodefinderwidgetinterface.cpp
debugging\qscriptdebuggercodefinderwidgetinterface.cpp(43) : fatal error C1083:
Cannot open include file: 'qscriptdebuggercodefinderwidgetinterface_p_p.h': No s
uch file or directory
qscriptdebuggercodefinderwidget.cpp
debugging\qscriptdebuggercodefinderwidget.cpp(43) : fatal error C1083: Cannot op
en include file: 'qscriptdebuggercodefinderwidgetinterface_p_p.h': No such file
or directory
qscriptdebugoutputwidgetinterface.cpp
qscriptdebugoutputwidget.cpp
qscriptbreakpointswidgetinterface.cpp
qscriptbreakpointswidget.cpp
qscriptbreakpointsmodel.cpp
qscripterrorlogwidgetinterface.cpp
qscripterrorlogwidget.cpp
qscriptenginedebugger.cpp
Generating Code...
NMAKE : fatal error U1077: '&amp;quot;C:\Program Files\Microsoft Visual Studio 8\VC\BIN\c
l.EXE&amp;quot;' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '&amp;quot;C:\Program Files\Microsoft Visual Studio 8\VC\BIN\n
make.exe&amp;quot;' : return code '0x2'
Stop.
NMAKE : fatal error U1077: 'cd' : return code '0x2'
Stop.&lt;/pre&gt;

&lt;p&gt;而且編一次都要很久，禁不起這種錯誤打擊的！編譯可以使用這個指令，是我試過 ok 的：&lt;/p&gt;

&lt;pre class="brush: bash;"&gt;configure -debug-and-release -no-sql-sqlite -no-qt3support -no-opengl -platform win32-msvc2005 -no-libtiff -no-dbus -no-phonon -no-phonon-backend -no-webkit &lt;/pre&gt;

&lt;p&gt;其中最重要的是要指定 -debug-and-release ，因為預設是不會產生 debug 版本，有時會有 debug 或是 trace 上的困擾。如果電腦上安裝多個開發環境，請透過 -platform win32-msvc2005 指定 toolchain&lt;/p&gt;

&lt;p&gt;nmake 後就是看 CPU 運動了！不過 vc 似乎無法吃光四核心 + 4G Ram 的效能 :(&lt;/p&gt;

&lt;h2&gt;好多 nmake &lt;/h2&gt;

&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/Sn6L2Iwl3NI/AAAAAAAAAks/qqryeMD4fYU/s1600-h/Qt_nmake%5B7%5D.jpg"&gt;&lt;img title="Qt_nmake" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="381" alt="Qt_nmake" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/Sn6L4Wn6ZWI/AAAAAAAAAkw/iBm6nykVOfE/Qt_nmake_thumb%5B5%5D.jpg?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;一個 cl&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/Sn6L7LALFsI/AAAAAAAAAk0/HClFwPKoXcU/s1600-h/Qt_cl%5B3%5D.jpg"&gt;&lt;img title="Qt_cl" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="373" alt="Qt_cl" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/Sn6L9EJXqEI/AAAAAAAAAk4/sx6DSMkD3yU/Qt_cl_thumb%5B1%5D.jpg?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;吃不了什麼 CPU 和 RAM&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/Sn6L_QSvTpI/AAAAAAAAAk8/NaXTo7JVX5w/s1600-h/Qt_CPU_Usage%5B3%5D.jpg"&gt;&lt;img title="Qt_CPU_Usage" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="373" alt="Qt_CPU_Usage" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/Sn6MBg8dCOI/AAAAAAAAAlA/6iz0czQ4edo/Qt_CPU_Usage_thumb%5B1%5D.jpg?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-3197499567705425848?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/3197499567705425848/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=3197499567705425848' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3197499567705425848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3197499567705425848'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/08/qt-452.html' title='Qt 4.5.2'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_2ZMoTkLFVu8/Sn6LzW0ttPI/AAAAAAAAAko/vfvSlolwGZw/s72-c/Qt_FTP_thumb%5B2%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-7065188712241131524</id><published>2009-08-09T16:05:00.001+08:00</published><updated>2010-02-14T11:21:01.293+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C++0x'/><category scheme='http://www.blogger.com/atom/ns#' term='翻譯'/><category scheme='http://www.blogger.com/atom/ns#' term='Concepts'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><title type='text'>The C++0x "Remove Concepts" Decision</title><content type='html'>&lt;p&gt;正如 &lt;a href="http://fsfoundry.org/codefreak/" target="_blank"&gt;COdEfr3@K&lt;/a&gt; 所說：&lt;a href="http://fsfoundry.org/codefreak/2009/07/21/cpp0x-concepts-rejected/" target="_blank"&gt;大件事&lt;/a&gt;！花了點時間 survey 一些網站~&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;大師說話了      &lt;ol&gt;       &lt;li&gt;&lt;a href="http://www.research.att.com/~bs/" target="_blank"&gt;Bjarne Stroustrup&lt;/a&gt;: &lt;a href="http://www.ddj.com/cpp/218600111" target="_blank"&gt;The C++0x “Remove Concepts” Decision&lt;/a&gt; &lt;/li&gt;        &lt;li&gt;Doug Gregor: &lt;a href="http://cpp-next.com/archive/2009/08/what-happened-in-frankfurt/" target="_blank"&gt;What Happened in Frankfurt?&lt;/a&gt; （由 &lt;a href="http://fsfoundry.org/codefreak/" target="_blank"&gt;COdEfr3@K&lt;/a&gt; 補充） &lt;/li&gt;        &lt;li&gt;&lt;a href="http://herbsutter.wordpress.com/" target="_blank"&gt;Herb Sutter&lt;/a&gt;: &lt;a href="http://herbsutter.wordpress.com/2009/07/21/trip-report/" target="_blank"&gt;Trip Report: Exit Concepts, Final ISO C++ Draft C++ Draft in ~18 Months&lt;/a&gt; &lt;/li&gt;        &lt;li&gt;&lt;a href="http://www.devx.com/cplus/Article/42448?trk=DXRSS_CPLUS" target="_blank"&gt;Bjarne Stroustrup Expounds on Concepts and the Future of C++&lt;/a&gt;&amp;#160; &lt;/li&gt;        &lt;li&gt;&lt;a href="http://www.informit.com/guides/guide.aspx?g=cplusplus" target="_blank"&gt;Danny Kalev&lt;/a&gt;:           &lt;ol&gt;           &lt;li&gt;&lt;a href="http://www.informit.com/guides/content.aspx?g=cplusplus&amp;amp;seqNum=441" target="_blank"&gt;The Removal of Concepts From C++0x&lt;/a&gt; &lt;/li&gt;            &lt;li&gt;&lt;a href="http://www.devx.com/cplus/Article/42365/0/page/1" target="_blank"&gt;The Rise and Fall of C++0x Concepts&lt;/a&gt; &lt;/li&gt;            &lt;li&gt;&lt;a href="http://www.informit.com/guides/content.aspx?g=cplusplus&amp;amp;seqNum=443" target="_blank"&gt;The Future of C++ 0x, Part 1&lt;/a&gt; &lt;/li&gt;         &lt;/ol&gt;       &lt;/li&gt;        &lt;li&gt;&lt;a href="http://www-949.ibm.com/software/rational/cafe/blogs/cpp-standard/2009/07/20/the-view-or-trip-report-from-the-july-2009-c-standard-meeting" target="_blank"&gt;The View (or trip report) from the July 2009 C++ Standard meeting&lt;/a&gt; &lt;/li&gt;        &lt;li&gt;&lt;a href="http://www-949.ibm.com/software/rational/cafe/blogs/cpp-standard/2009/07/20/the-view-or-trip-report-from-the-july-2009-c-standard-meeting-part-2" target="_blank"&gt;The View (or trip report) from the July 2009 C++ Standard meeting (Part 2)&lt;/a&gt; &lt;/li&gt;        &lt;li&gt;&lt;a href="http://pocoproject.org/blog/?p=236" target="_blank"&gt;Concepts Removed from C++0x&lt;/a&gt; &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt;    &lt;li&gt;鄉民的討論      &lt;ol&gt;       &lt;li&gt;&lt;a href="http://lambda-the-ultimate.org/node/3518" target="_blank"&gt;Concepts Get Voted Off The C++ 0x Island&lt;/a&gt; &lt;/li&gt;        &lt;li&gt;&lt;a href="http://www.artima.com/forums/flat.jsp?forum=270&amp;amp;thread=263251" target="_blank"&gt;The Removal of Concepts From C++0x&lt;/a&gt; &lt;/li&gt;        &lt;li&gt;&lt;a href="https://groups.google.com/group/pongba" target="_blank"&gt;TopLanguage&lt;/a&gt;: &lt;a href="https://groups.google.com/group/pongba/browse_frm/thread/9f4fdac795e6983f#" target="_blank"&gt;{C++} concept给毙了:(&lt;/a&gt; &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt;    &lt;li&gt;翻譯～&amp;#160; &lt;ol&gt;       &lt;li&gt;&lt;a href="http://www.cppprog.com/2009/0726/140.html" target="_blank"&gt;&lt;font color="#494949"&gt;&lt;/font&gt;Concept 的道路&lt;/a&gt; &lt;/li&gt;        &lt;li&gt;&lt;a href="http://www.cppprog.com/2009/0726/140_2.html" target="_blank"&gt;Concept 失敗的原因&lt;/a&gt; &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;下面是從 DDJ 翻譯的，讓 Bjarne 說說看整個事件吧 : )&lt;/p&gt;  &lt;h1&gt;The C++0x &amp;quot;Remove Concepts&amp;quot; Decision&lt;/h1&gt;  &lt;p&gt;在 2009 七月的德國法蘭克福會議上， C++ Standards Committee 決定將 concepts 移出 C++0x。雖然這對那些致力於 concepts 多年以及熟知 Concepts 潛力的人們來說是個沈重的打擊，但幸運地，移除 concepts 對大多數的程式設計師並不太有直接的影響。對於現實世界的軟體開發， C++0x 和 C++98 相比，仍舊是個更極具表達力（expressive）和更有效用的（effective）語言。 Committee 對於 remove concepts 的用意：在於希望能限制它帶能的風險與確保整個時程（&lt;i&gt;The committee acted with the intent to limit risk and preserve schedule&lt;/i&gt;），或許更好的 concepts 會在未來五年後出現。這篇文章將簡述移除 concepts 的理由以及 committee 做出此決定背後的的考量，此外也讓大家知道 C++ 的天還沒有塌下來啊～（儘管大把大把的謠言剛好說得相反！）&lt;/p&gt;  &lt;h1&gt;No &amp;quot;Concepts&amp;quot; in C++0x&lt;/h1&gt;  &lt;p&gt;2009 七月 &lt;a href="file://\\OC C++ Standards Committee" target="_blank"&gt;ISO C++ Standards Committee&lt;/a&gt; (WG21) 的法蘭克福會議上，在討論 concepts 應用在 specifying requirements for template arguments 時被&amp;quot;脫鉤（decoupled）&amp;quot;了，對於我來說，一個比較不那麼外交的用語是被&amp;quot;猛烈扯開(yanked out)&amp;quot;了，這代表 concepts 不會出現 C++0x 或是它的 library 裡頭，在我看來，這是 C++ 的一大挫敗，但不是災難一場（disaster）；一些替代方法都只會更糟。（That -- in my opinion -- is a major setback for C++, but not a disaster; and some alternatives were even worse）&lt;/p&gt;  &lt;p&gt;我在 concepts 已經努力超過七年了，而花了更甚於此的時間在解決這類問題。許多對於 concepts 的工作已經非常久了，舉例來說（按年代排序）：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Bjarne Stroustrup and Gabriel Dos Reis: &lt;a href="http://www.research.att.com/%7Ebs/N1522-concept-criteria.pdf"&gt;Concepts -- Design choices for template argument checking&lt;/a&gt;. October 2003. An early discussion of design criteria for &amp;quot;concepts&amp;quot; for C++. &lt;/li&gt;    &lt;li&gt;Bjarne Stroustrup: &lt;a href="http://www.research.att.com/%7Ebs/n1510-concept-checking.pdf"&gt;Concept checking -- A more abstract complement to type checking&lt;/a&gt;. October 2003. A discussion of models of &amp;quot;concept&amp;quot; checking. &lt;/li&gt;    &lt;li&gt;Bjarne Stroustrup and Gabriel Dos Reis: &lt;a href="http://www.research.att.com/%7Ebs/n1782-concepts-1.pdf"&gt;A concept design (Rev. 1)&lt;/a&gt;. April 2005. An attempt to synthesize a &amp;quot;concept&amp;quot; design based on (among other sources) N1510, N1522, and N1536. &lt;/li&gt;    &lt;li&gt;Jeremy Siek, Douglas Gregor, Ronald Garcia, Jeremiah Willcock, Jaakko Jarvi, and Andrew Lumsdaine: &lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1758.pdf"&gt;Concepts for C++0x&lt;/a&gt;. N1758==05-0018. May 2005. &lt;/li&gt;    &lt;li&gt;Gabriel Dos Reis and Bjarne Stroustrup: &lt;a href="http://www.research.att.com/%7Ebs/popl06.pdf"&gt;Specifying C++ Concepts&lt;/a&gt;. POPL06. January 2006. &lt;/li&gt;    &lt;li&gt;D. Gregor, B. Stroustrup: &lt;a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n2042.pdf"&gt;Concepts&lt;/a&gt;. N2042==06-0012. June 2006. The basis for all further &amp;quot;concepts&amp;quot; work for C++0x. &lt;/li&gt;    &lt;li&gt;Douglas Gregor, Jaakko Jarvi, Jeremy Siek, Bjarne Stroustrup, Gabriel Dos Reis, Andrew Lumsdaine: &lt;a href="http://www.research.att.com/%7Ebs/oopsla06.pdf"&gt;Concepts: Linguistic Support for Generic Programming in C++&lt;/a&gt;. OOPSLA'06, October 2006. An academic paper on the C++0x design and its experimental compiler &amp;quot;ConceptGCC.&amp;quot; &lt;/li&gt;    &lt;li&gt;Pre-Frankfurt working paper (with &amp;quot;concepts&amp;quot; in the language and standard library): &lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2914.pdf"&gt;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2914.pdf&lt;/a&gt; . N2914=09-0104. June 2009. &lt;/li&gt;    &lt;li&gt;B. Stroustrup: &lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2906.pdf"&gt;Simplifying the use of concepts&lt;/a&gt;. N2906=09-0096. June 2009. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h1&gt;&lt;/h1&gt;  &lt;p&gt;唉，這不用說，我跟其他人對於這件事感到相當失望，而事實上，一些替代方案都只是更糟、於事無補的，而我也無法提供快速、便利的解法。&lt;/p&gt;  &lt;p&gt;請注意到 C++0x 對於 C++ features 的改善與進步對大多數程式設計師看到和使用到的是沒有影響的。C++0x 與 C++98 相比，將仍舊是更具表達力的（expressive），它支援了：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Concurrent programming &lt;/li&gt;    &lt;li&gt;A better standard library &lt;/li&gt;    &lt;li&gt;許多的改善使得寫出好程式碼更加容易、簡單（像是更有效率、更好維護） &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;尤其，對於那些我給的 C++0x 範例，要是沒用到 concepts 或是 requires 的更是不受影響（像是在 &lt;a href="http://www.research.att.com/%7Ebs/hopl-almost-final.pdf"&gt;Evolving a language in and for the real world: C++ 1991-2006&lt;/a&gt; at ACM &lt;a href="http://portal.acm.org/toc.cfm?id=1238844"&gt;HOPL-III&lt;/a&gt; ）。請參考我寫的 &lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html"&gt;C++0x FAQ&lt;/a&gt;，一些人們甚至對於 C++0x 比他們想像中的還簡單而感到歡欣。&lt;/p&gt;  &lt;p&gt;Concepts 曾經是 C++0x 對於 template 有更好的理論基礎的重要核心 feature，像是說：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;提供更加穩固的 standard library specification &lt;/li&gt;    &lt;li&gt;扮演讓泛型程式設計（generic programming）成為主流使用的核心角色 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;現在，人們將在沒有語言的直接支援下使用 concepts。我對於未來最好的想像（scenario）是：我們在五年後的 C++ 裡頭得到了比現有 concepts 更好的 concepts。要能得到這樣的成果將會需要許多人非常專注的研究（但可不是&amp;quot;design by committee&amp;quot;喔！）。&lt;/p&gt;  &lt;h1&gt;What Happened?&lt;/h1&gt;  &lt;p&gt;Concepts 在過去幾年被發展出來，並在 2008 年，經過某些技術上的妥協後，進入到了 C++0x working paper 裡頭（妥協是自然而且必須的）。在實驗性的實作中已經足以應付&amp;quot;conceptualized&amp;quot; standard library，但還不到產品品質（but was not production quality），但我個人認為已經足夠稱為 proof of concept （POC）了！&lt;/p&gt;  &lt;p&gt;&lt;font color="#8080ff"&gt;（此段怕誤導、失真，段落後附有原文節錄）&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;我跟幾位 members 對於 concepts 有著同樣的考量：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Concepts 的設計，尤其是可用性（usability）這點，是否可為一般普通的程式設計師所掌握&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;會這麼說，是因為這決定了 concepts 設計的目標：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;使 generic progarmming 可被大多數的程式設計師接受[&lt;a href="http://www.research.att.com/%7Ebs/N1522-concept-criteria.pdf"&gt;BS&amp;amp;GDR2003&lt;/a&gt;]&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;但這目標在我現在看來已經做了極大的妥協：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Concepts 已經變成了（只存在）專家手上的工具，而不是一個讓 generic programming 更加可被接受的工具了。&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;過去一年半裡，我試著從使用者的角度去檢驗 C++0x，我擔心即用了 concepts 加持的 libraries 仍然對於程式設計師設下了一道新門檻。我覺得 concepts 的設計和它在 standard library 的使用並沒有充分反應我們過去幾年對於 concepts 的經驗。&lt;/p&gt;  &lt;p&gt;&lt;font color="#8080ff"&gt;「原文節錄」：&lt;/font&gt;My concern was with the design of &amp;quot;concepts&amp;quot; and in particular with the usability of &amp;quot;concepts&amp;quot; in the hands of &amp;quot;average programmers.&amp;quot; That concern was shared by several members. The stated aim of &amp;quot;concepts&amp;quot; was to make generic programming more accessible to most programmers [&lt;a href="http://www.research.att.com/%7Ebs/N1522-concept-criteria.pdf"&gt;BS&amp;amp;GDR2003&lt;/a&gt;], but that aim seemed to me to have been seriously compromised: Rather than making generic programming more accessible, &amp;quot;concepts&amp;quot; were becoming yet another tool in the hands of experts (only). Over the last half year or so, I had been examining C++0x from a user's point of view, and I worried that even use of libraries implemented using &amp;quot;concepts&amp;quot; would put new burdens on programmers. I felt that the design of &amp;quot;concepts&amp;quot; and its use in the standard library did not adequately reflect our experience with &amp;quot;concepts&amp;quot; over the last few years.&lt;/p&gt;  &lt;p&gt;接著，幾個月以前，Alisdair Meredith （一位極具洞察力的 UK committee）和 Howard Hinnant （the head of the standard library working group）問了幾個很好的問題，問題是關於：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;誰應該直接使用到 concepts、 &lt;/li&gt;    &lt;li&gt;使用 concepts 哪個部份、 &lt;/li&gt;    &lt;li&gt;如何使用 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;font color="#8080ff"&gt;「原文節錄」：&lt;/font&gt;who should directly use which parts of the &amp;quot;concepts&amp;quot; facilities and how&lt;/p&gt;  &lt;p&gt;這問題導引出各方考量以及不同角度出發對於 usability 的討論。最後，在經過多次令人混淆的討論後，我把我的結論放在 [&lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2906.pdf"&gt;BS2009&lt;/a&gt;]。&lt;/p&gt;  &lt;p&gt;幾個可能有點過度簡化的結論：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;現行定義的 concepts 難以使用，並將導致 concepts 不被使用（disuse），這可能是 template 不被使用或是 C++0x 不被公開採納。 &lt;/li&gt;    &lt;li&gt;一些簡化方法[&lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2906.pdf"&gt;BS2009&lt;/a&gt;]仍舊可以描述 concepts ，使得 C++0x 可以出貨或是僅須稍稍的修改。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;請注意到：這只是個非常簡略、囫圇吞棗的結論，standards committee 在討論時是非常有 polite 的，我們有著同樣的目標，總是避免直接的針鋒相對、對質詢問。不幸的是，當時的（內部）討論實在過於龐雜（許許多多牽涉到細節或沒有牽涉到細節的訊息）、令人困惑，在對於問題的定位及如何處理沒有浮現共識下，我在法蘭克福會議裡頭報告了幾項替代方案：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&amp;quot;fix and ship&amp;quot;      &lt;ul&gt;       &lt;li&gt;Remaining work: remove explicit &amp;quot;concepts,&amp;quot; add explicit refinement, add &amp;quot;concept&amp;quot;/type matching, handle &amp;quot;concept&amp;quot; map scope problems &lt;/li&gt;        &lt;li&gt;Risks: no implementation, complexity of description &lt;/li&gt;        &lt;li&gt;Schedule: no change or one meeting &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;&amp;quot;Yank and ship&amp;quot;      &lt;ul&gt;       &lt;li&gt;Remaining work: yank (core and standard library) &lt;/li&gt;        &lt;li&gt;Risks: old template problems remain, disappointment in &amp;quot;progressive&amp;quot; community (&amp;quot;seven year's work down the drain&amp;quot;) &lt;/li&gt;        &lt;li&gt;Schedule: five years to &amp;quot;concepts&amp;quot; (complete redesign needed) or never &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;&amp;quot;Status quo&amp;quot;      &lt;ul&gt;       &lt;li&gt;Remaining work: details &lt;/li&gt;        &lt;li&gt;Risks: unacceptable programming model, complexity of description (alternative view: none) &lt;/li&gt;        &lt;li&gt;Schedule: no change &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;我和一些其他的人贊同第一個方案（&amp;quot;fix and ship&amp;quot;）並認為這是可行的。然而，大多數的 committee 不是這麼認為，他們選擇了第二個方案（&amp;quot;yank and ship,&amp;quot; renaming it &amp;quot;decoupling&amp;quot;）。在我看來兩者都比第三個方案（&amp;quot;status quo&amp;quot;）好，我對於投票結果的解讀是這樣的&lt;font color="#8080ff"&gt;：（這段怕有情緒性字眼，也保留原文）&lt;/font&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;對於 concepts 的支持者而言，他們沒有一個共識，整個想法看起來太過爭議 &lt;/li&gt;    &lt;li&gt;一些人則是擔心 C++0x 雄心勃勃的時程表開始（ㄜ，在我不公正地看來，開始指責 concepts） &lt;/li&gt;    &lt;li&gt;一些人則是從頭到尾對於 concepts 就是興致缺缺 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;font color="#8080ff"&gt;「原文節錄」：&lt;/font&gt;My interpretation of that vote is that given the disagreement among proponents of &amp;quot;concepts,&amp;quot; the whole idea seemed controversial to some, some were already worried about the ambitious schedule for C++0x (and, unfairly IMO, blamed &amp;quot;concepts&amp;quot;), and some were never enthusiastic about &amp;quot;concepts.&amp;quot; &lt;/p&gt;  &lt;p&gt;有鑑於此，&amp;quot;fixing concepts&amp;quot;不再是一個迫於現實的選則了，本質來說，所有對於 concepts 的支持都將是更久之後的事（&amp;quot;later&amp;quot; and &amp;quot;eventually&amp;quot;）。我對於現在把 concepts 移除這件事也提出了會有無可避免的延遲的警告， 因為在沒有時程的壓力下，所有的設計抉擇都將被重新評估（&lt;font color="#8080ff"&gt;譯注&lt;/font&gt;：我想是對於 concepts 的設計抉擇）。&lt;/p&gt;  &lt;p&gt;&lt;font color="#8080ff"&gt;「原文節錄」：&lt;/font&gt;I warned that a long delay was inevitable if we removed &amp;quot;concepts&amp;quot; now because in the absence of schedule pressures, essentially all design decisions will be re-evaluated.&lt;/p&gt;  &lt;p&gt;令人驚訝的（或許吧），在法蘭克福的會議上沒有關於 concepts 的技術報告和討論。整個討論都只著重在時間問題上，我想這投票結果主要反應時間考量吧～&lt;/p&gt;  &lt;p&gt;請不要譴責 committee 的謹慎，這不是 &amp;quot;Bjarne vs. the committee fight&amp;quot;， 而是試著在大多數人的考量中取得平衡點。我跟其他人會失望，是因為我們沒有抓住&amp;quot;fix and ship&amp;quot;這個機會，而且 C++ 不是一個學院派、實驗性質的語言，除非成員們相信這麼做對於程式碼撰寫上帶來的風險非常低，否則他們就得、也必須拒絕接受它。整體來說，committee 代表的是數十億行程式碼，舉例來說，如果 C++0x 無法被公開採納或是無法在有 concepts 的情況下讓 unconstrained templates 得到長期的使用，C++ 社群將會分崩離析。因此，一個很虛（poor）的 concepts 設計可能會比沒有 concepts 帶來更糟的後果。兩難之間，我也選擇了移除 concepts ，我寧願選擇挫敗也不要一個災難來臨。&lt;/p&gt;  &lt;h1&gt;Technical Issues&lt;/h1&gt;  &lt;p&gt;懸而未解的 concepts，其問題在於，當把焦點放到 distinction between explicit and implicit &amp;quot;concept&amp;quot; maps 時(參考 [&lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2906.pdf"&gt;BS2009&lt;/a&gt;]): &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Should a type that meets the requirements of a &amp;quot;concept&amp;quot; automatically be accepted where the &amp;quot;concept&amp;quot; is required (e.g. should a type &lt;b&gt;X&lt;/b&gt; that provides +, -, *, and / with suitable parameters automatically match a &amp;quot;concept&amp;quot; &lt;b&gt;C&lt;/b&gt; that requires the usual arithmetic operations with suitable parameters) or should an additional explicit statement (a &amp;quot;concept&amp;quot; map from &lt;b&gt;X&lt;/b&gt; to &lt;b&gt;C&lt;/b&gt;) that a match is intentional be required? (My answer: Use automatic match in almost all cases). &lt;/li&gt;    &lt;li&gt;Should there be a choice between &lt;i&gt;automatic&lt;/i&gt; and &lt;i&gt;explicit&lt;/i&gt; &amp;quot;concepts&amp;quot; and should a designer of a &amp;quot;concept&amp;quot; be able to force every user to follow his choice? (My answer: All &amp;quot;concepts&amp;quot; should be automatic). &lt;/li&gt;    &lt;li&gt;Should a type &lt;b&gt;X&lt;/b&gt; that provides a member operation &lt;b&gt;X::begin()&lt;/b&gt; be considered a match for a &amp;quot;concept&amp;quot; &lt;b&gt;C&amp;lt;T&amp;gt;&lt;/b&gt; that requires a function &lt;b&gt;begin(T)&lt;/b&gt; or should a user supply a &amp;quot;concept&amp;quot; map from &lt;b&gt;T&lt;/b&gt; to &lt;b&gt;C&lt;/b&gt;? An example is &lt;b&gt;std::vector&lt;/b&gt; and &lt;b&gt;std::Range&lt;/b&gt;. (My answer: It should match). &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;我的建議和在&amp;quot;status quo before Frankfurt&amp;quot; 提到的解法（answer）是完全不同的。很明顯地，在這裡我必須忽略大部份的細節和設計理念、簡化一下我的解釋。&lt;/p&gt;  &lt;p&gt;我無法在這裡重現整個技術討論，但是下面是我的結論：在 &amp;quot;status quo&amp;quot; 的設計裡頭， &amp;quot;concept&amp;quot; maps 被用來做到兩件事：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;To map types to &amp;quot;concepts&amp;quot; by adding/mapping attributes and &lt;/li&gt;    &lt;li&gt;To assert that a type matches a &amp;quot;concept.&amp;quot; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;不知何故（Somehow），後者未被視作不幸的、少見的必要性，反而被視為基本的功能。當兩個 concepts 有著語意上的差別時，我們需要的不是一個用來說明這個 type 符合這個 concept 但不符合那個 concept 的 assertion （這充其量，只是種 workaround，一種不直接接、用說明回擊問題本身的手法，原文：this is, at best, a workaround -- an indirect and elaborate attack on the fundamental problem），而是一個 assertion 可以說明這 type 帶有與這 concept 相同的語意，但沒有另外一個&amp;#160; concept 的語意。（fulfills the axiom(s) of the one and not the other &amp;quot;concept&amp;quot;）&lt;/p&gt;  &lt;p&gt;&lt;font color="#8080ff"&gt;「原文節錄」：&lt;/font&gt;Somehow, the latter came to be seen an essential function by some people, rather than an unfortunate rare necessity. When two &amp;quot;concepts&amp;quot; differ semantically, what is needed is not an assertion that a type meets one and not the other &amp;quot;concept&amp;quot; (this is, at best, a workaround -- an indirect and elaborate attack on the fundamental problem), but an assertion that a type has the semantics of the one and not the other &amp;quot;concepts&amp;quot; (fulfills the axiom(s) of the one and not the other &amp;quot;concept&amp;quot;).&lt;/p&gt;  &lt;p&gt;舉例來說， STL 的 &lt;b&gt;input&lt;/b&gt; iterator 和 &lt;b&gt;forward&lt;/b&gt; iterator 有著關鍵性的語意差別：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;You can traverse a sequence defined by &lt;b&gt;forward&lt;/b&gt; iterators twice, but not a sequence defined by &lt;b&gt;input&lt;/b&gt; iterators; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;像是，在 input stream 上施行 multi-pass algorithm 不是個好主意！在 &amp;quot;status quo&amp;quot; 解法中，會強迫每個使用者說明：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;What types match a &lt;b&gt;forward&lt;/b&gt; iterator and what types match an &lt;b&gt;input&lt;/b&gt; iterator&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;而我的建議的解決方式是：&lt;/p&gt;  &lt;p&gt;若且唯若（If (and only if)）&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;你想使用的語意並不是兩個 concepts 的共同部份， &lt;/li&gt;    &lt;li&gt;而且 compiler 無法幫你推導出哪個 concept 才是較好的 metch 時， &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;你必須說明 type 的語意，像是說：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;my type supports multi-pass semantics.&amp;quot;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;其他人則可能是這麼說：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;When all you have is a 'concept' map, everything looks like needing a type/'concept' assertion.&amp;quot;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;在法蘭克福的會議上，我是這樣做結論的： &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Why do we want &amp;quot;concepts&amp;quot;?      &lt;ul&gt;       &lt;li&gt;To make requirement on types used as template arguments explicit          &lt;ul&gt;           &lt;li&gt;Precise documentation &lt;/li&gt;            &lt;li&gt;Better error messages &lt;/li&gt;            &lt;li&gt;Overloading &lt;/li&gt;         &lt;/ul&gt;       &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;不同的人們有不同的出發點以及排出不同的優先順序，然而，站在這高階的角度來看，可能會有些混淆，但應該是極少或不相衝突的。每個合理的、才走一半的 concept design 都提供了這些特性。&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;What concerns do people have?      &lt;ul&gt;       &lt;li&gt;Programmability &lt;/li&gt;        &lt;li&gt;Complexity of formal specification &lt;/li&gt;        &lt;li&gt;Compile time &lt;/li&gt;        &lt;li&gt;Run time &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;我個人關注的是 programmability (ease of use, generality, teachability, scalability) ，其次是正式規格書的 complexity （40 頁的標準文件），再其他則關於 compiler time 和 run time 的考量。然而，我覺得實驗性質的實作（ConceptGCC [&lt;a href="http://www.research.att.com/%7Ebs/oopsla06.pdf"&gt;Gregor2006&lt;/a&gt;]）中，constrained templates （使用 concepts）的 run time 可以做的跟 nonconstrained templates 一樣好、甚至更好。ConceptGCC 實際上非常慢，但我並未將它視為根本考量，當它用來驗證一個想法時，我們陷入了傳統上的兩難。這裡描述一下有點過度簡化的兩難問題：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&amp;quot;Don't standardize without commercial implementation&amp;quot; &lt;/li&gt;    &lt;li&gt;&amp;quot;Major implementers do not implement without a standard&amp;quot; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;各方面來說，細節設計和實驗實作構成了基本的妥協。&lt;/p&gt;  &lt;p&gt;我對 concepts 的原則是：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Duck typing      &lt;ul&gt;       &lt;li&gt;The key to the success of templates for GP (compared to OO with interfaces and more) &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Substitutability      &lt;ul&gt;       &lt;li&gt;Never call a function with a stronger precondition than is &amp;quot;guaranteed&amp;quot; &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;&amp;quot;Accidental match&amp;quot; is a minor problem      &lt;ul&gt;       &lt;li&gt;Not in the top 100 problems &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;我對於 concepts 的&amp;quot;minimal fixes&amp;quot;寫在 pre-Frankfurt working paper：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&amp;quot;Concepts&amp;quot; are implicit/auto      &lt;ul&gt;       &lt;li&gt;To make duck typing the rule &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Explicit refinement      &lt;ul&gt;       &lt;li&gt;To handle substitutability problems &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;General scoping of &amp;quot;concept&amp;quot; maps      &lt;ul&gt;       &lt;li&gt;To minimize &amp;quot;implementation leakage&amp;quot; &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Simple type/&amp;quot;concept&amp;quot; matching      &lt;ul&gt;       &lt;li&gt;To make vector a range without redundant &amp;quot;concept&amp;quot; map &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;細節請參考 [&lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2906.pdf"&gt;BS2009&lt;/a&gt;]。&lt;/p&gt;  &lt;h1&gt;No C++0x, Long Live C++1x&lt;/h1&gt;  &lt;p&gt;即使在 concepts 已經被移除後，下一版的 C++ standard 仍可能延遲推出。悲慘地說，將不會有 C++0x 了（除非你把 C++0x 這個小改版算進去）。我們一定得等到 C++1x，希望這個 x 是個很小的數字。希望還是在的，因為 C++1x 已經 feature complete 了（除非標準對於一些在 formal proposal for the standard 還有所堅持）。 &amp;quot;所有&amp;quot; 剩下、懸而未決的都只是龐雜的技術問題和意見了。&lt;/p&gt;  &lt;p&gt;在我的 &lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html"&gt;C++0x FAQ&lt;/a&gt; 中你可以看到一些 features 和討論，這裡僅是列出部份： &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#atomics"&gt;atomic operations&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#auto"&gt;auto (type deduction from initializer) &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#C99"&gt;C99 features &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#enum"&gt;enum class (scoped and strongly typed enums) &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#constexpr"&gt;constant expressions (generalized and guaranteed; &lt;b&gt;constexpr&lt;/b&gt;) &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#default"&gt;defaulted and deleted functions (control of defaults) &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#delegating-ctor"&gt;delegating constructors &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#member-init"&gt;in-class member initializers &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#inheriting"&gt;inherited constructors &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#init-list"&gt;initializer lists (uniform and general initialization) &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#lambda"&gt;lambdas &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#XXX"&gt;memory model &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#rval"&gt;move semantics; see rvalue references &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#nullptr"&gt;null pointer (&lt;b&gt;nullptr&lt;/b&gt;)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#for"&gt;range for statement &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#raw-strings"&gt;raw string literals &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#template-alias"&gt;template alias &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#thread-local"&gt;thread-local storage &lt;/a&gt;(&lt;b&gt;thread_local&lt;/b&gt;) &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#unicode"&gt;unicode characters &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#uniform-init"&gt;Uniform initialization &lt;/a&gt;syntax and semantics &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#UD-literals"&gt;user-defined literals &lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#variadic-templates"&gt;variadic templates &lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;和 libraries: &lt;/p&gt;  &lt;li&gt;Improvements to &lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#XXX"&gt;algorithms &lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#std-array%20array%3C/a%3E%20%3Cli%3E%20Improvements%20to%20%3Ca%20href="&gt;containers&lt;/a&gt; &lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#std-duration"&gt;duration and time_point&lt;/a&gt; &lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#std-function"&gt;function and bind&lt;/a&gt; &lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#std-forward_list"&gt;forward_list a singly-liked list &lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#std-future"&gt;future and promise&lt;/a&gt; &lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#gc-abi"&gt;garbage collection ABI&lt;/a&gt; &lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#std-unordered"&gt;hash_tables&lt;/a&gt;; see &lt;b&gt;unordered_map &lt;/b&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#XXX"&gt;metaprogramming and type traits&lt;/a&gt; &lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#std-random"&gt;random number generators &lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#std-regex"&gt;regex a regular expression library &lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#XXX"&gt;scoped allocators &lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#std-unique_ptr"&gt;smart pointers&lt;/a&gt;; see &lt;b&gt;shared_ptr&lt;/b&gt;, &lt;b&gt;weak_ptr&lt;/b&gt;, and &lt;b&gt;unique_ptr&lt;/b&gt; &lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#std-thread"&gt;threads&lt;/a&gt; &lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#std-atomics"&gt;atomic operations &lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.research.att.com/%7Ebs/C++0xFAQ.html#std-tuple"&gt;tuple &lt;/a&gt;    &lt;p&gt;即使沒有了 concepts，C++1x 仍將會是個基於 C++98 大量改善的版本，尤其當你注意到這些 features 都讓你可以在最大的表達力（expressiveness）和彈性（flexibility）間的互動的。我希望我們會在新版的 C++ （或許五年後）中看到 concepts ，也或許我們應該稱呼 C++1y 或是 C++y！&lt;/p&gt;    &lt;h1&gt;心得&lt;/h1&gt;    &lt;p&gt;該看書了 &amp;gt;__&amp;lt;&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;&lt;/p&gt; &lt;/li&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-7065188712241131524?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/7065188712241131524/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=7065188712241131524' title='7 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/7065188712241131524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/7065188712241131524'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/08/c0x-concepts-decision.html' title='The C++0x &amp;quot;Remove Concepts&amp;quot; Decision'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-6864801413877746005</id><published>2009-08-07T23:58:00.001+08:00</published><updated>2009-08-07T23:59:16.651+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>How Lord of The Rings Should Have Ended</title><content type='html'>&lt;center&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/1yqVD0swvWU&amp;amp;hl=zh_TW&amp;amp;fs=1&amp;amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/1yqVD0swvWU&amp;amp;hl=zh_TW&amp;amp;fs=1&amp;amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/center&gt;  &lt;p&gt;讓我想到小時候寫作文應該要：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;小題大做 &lt;/li&gt;    &lt;li&gt;大題小做 &lt;/li&gt;    &lt;li&gt;不要做作 &lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-6864801413877746005?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/6864801413877746005/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=6864801413877746005' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/6864801413877746005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/6864801413877746005'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/08/how-lord-of-rings-should-have-ended.html' title='How Lord of The Rings Should Have Ended'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-5464465083167845937</id><published>2009-08-07T23:04:00.001+08:00</published><updated>2009-08-07T23:07:26.519+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Boost'/><category scheme='http://www.blogger.com/atom/ns#' term='翻譯'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Program_options'/><title type='text'>Boost.Program_options – Tutorial – Option Details and Multiples Sources</title><content type='html'>&lt;h1&gt;Vocabulary&lt;/h1&gt;  &lt;ol&gt;   &lt;li&gt;Program options, options &lt;/li&gt;    &lt;li&gt;pair. (name, value) &lt;/li&gt;    &lt;li&gt;Token &lt;/li&gt;    &lt;li&gt;Position options&lt;/li&gt;    &lt;li&gt;Composing options&lt;/li&gt; &lt;/ol&gt;  &lt;h1&gt;Option Details&lt;/h1&gt;  &lt;p&gt;沒錯，你得到它了！option value 不僅只侷限於 int 型別，此外還可以有其它下面的屬性（proerties）。完整程式可以在&lt;/p&gt;  &lt;pre class="brush: bash;"&gt;example/options_description.cpp&lt;/pre&gt;

&lt;p&gt;找到。&lt;/p&gt;

&lt;p&gt;想像你在寫一個 compiler ，你可以設定它的 options：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Otimization level &lt;/li&gt;

  &lt;li&gt;Include paths &lt;/li&gt;

  &lt;li&gt;Input files &lt;/li&gt;

  &lt;li&gt;其它做些有趣的事。 &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;下面的程式碼試著描述這些 options ：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;int opt;
po::options_description desc(&amp;quot;Allowed options&amp;quot;);
desc.add_options()
    (&amp;quot;help&amp;quot;, &amp;quot;produce help message&amp;quot;)
    (&amp;quot;optimization&amp;quot;, po::value&amp;lt;int&amp;gt;(&amp;amp;opt)-&amp;gt;default_value(10), 
  &amp;quot;optimization level&amp;quot;)
    (&amp;quot;include-path,I&amp;quot;, po::value&amp;lt; vector&amp;lt;string&amp;gt; &amp;gt;(), 
  &amp;quot;include path&amp;quot;)
    (&amp;quot;input-file&amp;quot;, po::value&amp;lt; vector&amp;lt;string&amp;gt; &amp;gt;(), &amp;quot;input file&amp;quot;)
;&lt;/pre&gt;

&lt;ol&gt;
  &lt;li&gt;help：就像上個範例一樣。最好讓每個 case 都有自己的 help option。 &lt;/li&gt;

  &lt;li&gt;optimization：這裡的 optimization 有兩個特點： 
    &lt;ol&gt;
      &lt;li&gt;我們在程式裡頭指定了變數的位址（&amp;amp;opt）。如此一來，當 values 被分析儲存後，我們就可以透過該變數取得 optimization 的 value。 &lt;/li&gt;

      &lt;li&gt;我們指定了變數的 default value 為 10 。因此，當使用者沒有給 optimization 指定一個 value 時， value 會是 10。 &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;

  &lt;li&gt;include-path：include-path 在這裡是一個特殊的例子，它只從 command line 讀入資料來使用 options_description。（原文是：The &amp;quot;include-path&amp;quot; option is an example of the only case where the interface of the options_description class serves only one source -- the command line.&amp;#160; 看了上下文，總覺得這句有點詭異、跳 tone）。對於常用到的 options，使用者往往喜歡使用它們的 short option name 形式，而這也就是程式碼裡頭 &amp;quot;include-path,I&amp;quot; option name 想表達的意思：&amp;quot;I&amp;quot; 是 include-path 的 short name。 
    &lt;br /&gt;另外，值得注意的是 &lt;code&gt;&amp;quot;include-path&amp;quot;&lt;/code&gt; 的型別是 &lt;font color="#0080ff"&gt;std::vector&lt;/font&gt;。Boost.Program_options 對於 vectors 有特別的支援，它可以多次出現在 option 輸入中，而所有的 values 都會被存放在一個 vector 裡頭。 &lt;/li&gt;

  &lt;li&gt;input-file：描述了一連串、將被處理的檔案。當然，一開始的時候像下面的方式指定 input file 是可以的： 
    &lt;br /&gt;

    &lt;pre class="brush: bash;"&gt;compiler --input-file=a.cpp&lt;/pre&gt;
但，如果和下面的方法相比，上面的方式似乎就有點不標準囉！ 

    &lt;br /&gt;

    &lt;pre class="brush: bash;"&gt;compiler a.cpp&lt;/pre&gt;

    &lt;br /&gt;我們將針對這問題來探討一下： &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;像 a.cpp 這種在 parsing 的時候找不到 option name 的 token 的，在 Boost.Program_options 裡頭稱為 &lt;font color="#0080ff"&gt;positional options&lt;/font&gt;。透過一些使用者的幫助，Boost.Program_options 有辦法可以知道 a.cpp 實際上就是 &amp;quot;--input-file=a.cpp&amp;quot; ，下面是妳/你需要的額外程式碼：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;po::positional_options_description p;
p.add(&amp;quot;input-file&amp;quot;, -1);

po::variables_map vm;
po::store(po::command_line_parser(ac, av).
          options(desc).positional(p).run(), vm);
po::notify(vm);&lt;/pre&gt;

&lt;p&gt;開始兩行程式碼的意思是：所有的 positional options 需要被轉會成 &amp;quot;input-file&amp;quot; options。此外，這邊我們使用 &lt;font color="#0080ff"&gt;command_line_parser&lt;/font&gt; 類別，而不是 &lt;font color="#0080ff"&gt;parse_command_line function&lt;/font&gt;。parse_command_line 是一個只在簡單情況下會用到的 wrapper function 而已，但我們現在需要更多的資訊來做正確分析。&lt;/p&gt;

&lt;p&gt;現在，所有的 options 都已經被描述和分析了，我們就饒了自己吧，不要去管怎麼實作 compiler 的邏輯、細節，先用 print 的方式來表示各個 options。&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;if (vm.count(&amp;quot;include-path&amp;quot;))
{
    cout &amp;lt;&amp;lt; &amp;quot;Include paths are: &amp;quot; 
         &amp;lt;&amp;lt; vm[&amp;quot;include-path&amp;quot;].as&amp;lt; vector&amp;lt;string&amp;gt; &amp;gt;() &amp;lt;&amp;lt; &amp;quot;\n&amp;quot;;
}

if (vm.count(&amp;quot;input-file&amp;quot;))
{
    cout &amp;lt;&amp;lt; &amp;quot;Input files are: &amp;quot; 
         &amp;lt;&amp;lt; vm[&amp;quot;input-file&amp;quot;].as&amp;lt; vector&amp;lt;string&amp;gt; &amp;gt;() &amp;lt;&amp;lt; &amp;quot;\n&amp;quot;;
}

cout &amp;lt;&amp;lt; &amp;quot;Optimization level is &amp;quot; &amp;lt;&amp;lt; opt &amp;lt;&amp;lt; &amp;quot;\n&amp;quot;;     &lt;/pre&gt;

&lt;p&gt;下面是個編譯、執行這個範例的方法：&lt;/p&gt;

&lt;pre class="brush: bash;"&gt;$bin/gcc/debug/options_description --help
Usage: options_description [options]
Allowed options:
  --help                 : produce help message
  --optimization arg     : optimization level
  -I [ --include-path ] arg : include path
  --input-file arg       : input file
$bin/gcc/debug/options_description
Optimization level is 10
$bin/gcc/debug/options_description --optimization 4 -I foo a.cpp
Include paths are: foo
Input files are: a.cpp
Optimization level is 4&lt;/pre&gt;

&lt;p&gt;歐喔，還有一個小問題！我們還是可以使用&amp;quot;input-file&amp;quot;來指定，而 Usage 也是這樣寫的，這可能會混淆了我們的使用者，如果能把這資訊隱藏應該會不錯，不過就留到下一個例子吧。&lt;/p&gt;

&lt;h1&gt;Multiptles Sources&lt;/h1&gt;

&lt;p&gt;很快地，妳/你就會發現都得把所有的 compiler options 填好是一件令人抓狂的事。想想看，難道妳/你希望使用者裝了一個新的 library 後每次使用妳/你的 compiler 都得一個一個把 options 填好嗎？如果能她/他決定了一些選項是每次都要使用到的呢？最好的情況是產生一個 common settings 然後搭配 command line 來使用。&lt;/p&gt;

&lt;p&gt;當然，把 config file 跟 command line 搭配使用是有必要的。舉例來說：config file 的 optimization level 會被 command line 的輸入蓋過；然而 include path 卻是需要有累加效果的。&lt;/p&gt;

&lt;p&gt;來看個 code 先，完整的程式可以在&lt;/p&gt;

&lt;pre class="brush: bash;"&gt;example/multiple_sources.cpp&lt;/pre&gt;

&lt;p&gt;找到。option 定義有兩個有趣的點：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;我們宣告了多個 options_descriptions 實體（instances）。為什麼呢？因為不是所有的 options 都是相近的，有些 options，像是 input-file 不應該出現在自動化 help message 裡頭；有些 options 只在 config files 裡頭才有意義。 &lt;/li&gt;

  &lt;li&gt;最後，讓 help message 有點結構化、而不只是串列表是不錯的主意。 &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;下面讓我們宣告幾個 option groups 吧：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;// Declare a group of options that will be 
// allowed only on command line
po::options_description generic(&amp;quot;Generic options&amp;quot;);
generic.add_options()
    (&amp;quot;version,v&amp;quot;, &amp;quot;print version string&amp;quot;)
    (&amp;quot;help&amp;quot;, &amp;quot;produce help message&amp;quot;)    
    ;
    
// Declare a group of options that will be 
// allowed both on command line and in
// config file
po::options_description config(&amp;quot;Configuration&amp;quot;);
config.add_options()
    (&amp;quot;optimization&amp;quot;, po::value&amp;lt;int&amp;gt;(&amp;amp;opt)-&amp;gt;default_value(10), 
          &amp;quot;optimization level&amp;quot;)
    (&amp;quot;include-path,I&amp;quot;, 
         po::value&amp;lt; vector&amp;lt;string&amp;gt; &amp;gt;()-&amp;gt;composing(), 
         &amp;quot;include path&amp;quot;)
    ;

// Hidden options, will be allowed both on command line and
// in config file, but will not be shown to the user.
po::options_description hidden(&amp;quot;Hidden options&amp;quot;);
hidden.add_options()
    (&amp;quot;input-file&amp;quot;, po::value&amp;lt; vector&amp;lt;string&amp;gt; &amp;gt;(), &amp;quot;input file&amp;quot;)
    ;        &lt;/pre&gt;

&lt;p&gt;請注意到宣告 include-path option 時呼叫的 &lt;font color="#0080ff"&gt;composing&lt;/font&gt; method，這告訴了 library 不同來源的 values 應該被組合在一起（composed together）。&lt;/p&gt;

&lt;p&gt;我們可以用 options_description 的 add method 來進一步的組織 option groups 中：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;po::options_description cmdline_options;
cmdline_options.add(generic).add(config).add(hidden);

po::options_description config_file_options;
config_file_options.add(config).add(hidden);

po::options_description visible(&amp;quot;Allowed options&amp;quot;);
visible.add(generic).add(config);&lt;/pre&gt;

&lt;p&gt;分析和儲存 values 跟以往的作法相同，除了我們得額外呼叫了 &lt;font color="#0080ff"&gt;parse_config_file&lt;/font&gt; 和呼叫 &lt;font color="#0080ff"&gt;store&lt;/font&gt; 兩次之外。如果有些 value 在 command line 和 config file 中都出現了，那會發生什麼事？通常來說，先儲存下來的 value 會被視為優先，這也是 -optimization option 的設計，而對於 &lt;font color="#0080ff"&gt;composing options&lt;/font&gt; 來說（像是 include-file ），這些 values 則是會被合併。&lt;/p&gt;

&lt;p&gt;下面是個編譯、執行這個範例的方法：&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;$bin/gcc/debug/multiple_sources
Include paths are: /opt
Optimization level is 1
$bin/gcc/debug/multiple_sources --help
Allows options:

Generic options:
  -v [ --version ]       : print version string
  --help                 : produce help message

Configuration:
  --optimization n       : optimization level
  -I [ --include-path ] path : include path

$bin/gcc/debug/multiple_sources --optimization=4 -I foo a.cpp b.cpp
Include paths are: foo /opt
Input files are: a.cpp b.cpp
Optimization level is 4&lt;/pre&gt;

&lt;br /&gt;

&lt;p&gt;第一個呼叫是使用 config file。第二個則多使用了 command line 的輸入。正如我們所看到的，include path 的 value 是從 command line 和 config file 合併來的，而 optimization 則是從 command line 取得。&lt;/p&gt;

&lt;h2&gt;Reference&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Boost 1.39.0 Doc: &lt;a href="http://www.boost.org/doc/libs/1_39_0/doc/html/program_options.html" target="_blank"&gt;Chapter 13. Boost.Program_options&lt;/a&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;See Also&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href="http://keikoblog.blogspot.com/2009/08/boostprogramoptions-introduction-and.html" target="_blank"&gt;Boost.Program_options – Introduction and Tutorial&lt;/a&gt;&amp;#160;&lt;/li&gt;
&lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-5464465083167845937?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/5464465083167845937/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=5464465083167845937' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5464465083167845937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5464465083167845937'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/08/boostprogramoptions-tutorial-option.html' title='Boost.Program_options – Tutorial – Option Details and Multiples Sources'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-4806787934695446527</id><published>2009-08-07T13:18:00.001+08:00</published><updated>2009-08-07T23:07:41.936+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Boost'/><category scheme='http://www.blogger.com/atom/ns#' term='翻譯'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><category scheme='http://www.blogger.com/atom/ns#' term='Boost.Program_options'/><title type='text'>Boost.Program_options – Introduction and Tutorial</title><content type='html'>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;最近因為需要一些自動化的程式看了 Boost.Program_options 這個 library ，這系列文章主要內容都是&lt;font color="#ff0000"&gt;翻譯&lt;/font&gt;自 &lt;a href="http://www.boost.org/doc/libs/1_39_0/doc/html/program_options.html" target="_blank"&gt;Boost 1.39.0 Doc&lt;/a&gt; 裡頭，希望還有點時間可以加上一些 trace 的心得和紀錄，希望沒有誤人子弟、教壞&lt;a href="http://dict.revised.moe.edu.tw/cgi-bin/newDict/dict.sh?cond=%A6_&amp;amp;pieceLen=50&amp;amp;fld=1&amp;amp;cat=&amp;amp;ukey=-2065727139&amp;amp;serial=1&amp;amp;recNo=0&amp;amp;op=f&amp;amp;imgFont=1" target="_blank"&gt;囝&lt;/a&gt;仔大小、對大家有幫助～&lt;/p&gt;  &lt;h1&gt;Vocabulary&lt;/h1&gt;  &lt;ol&gt;   &lt;li&gt;Program options, options &lt;/li&gt;    &lt;li&gt;Config file &lt;/li&gt;    &lt;li&gt;Command line &lt;/li&gt;    &lt;li&gt;pair. (name, value) &lt;/li&gt; &lt;/ol&gt;  &lt;h1&gt;Introduction&lt;/h1&gt;  &lt;p&gt;Boost.Program_options 是個可以讓程式設計師獲得 program options 的函式庫，什麼是 program options 呢？就是那種由使用者提供，可能是 command line 或是 config file 的 &lt;font color="#ff0000"&gt;(name, value) 組合（pairs）&lt;/font&gt;。&lt;/p&gt;  &lt;p&gt;那為什麼需要使用 Boost.Program_options 呢？為什麼說它比我們依靠直覺寫出來的程式碼還好呢？&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;簡單。Boost.Program_options 很小、提供的新增 options 的語法也簡單。像是自動化的 option value 的型別轉換（type conversion）、變數存放。 &lt;/li&gt;    &lt;li&gt;比較好的錯誤回報。 當分析（parsing）command line input 出錯時，Boost.Program_options 會回報所有的錯誤，但 hand-written code 可能會誤判。 &lt;/li&gt;    &lt;li&gt;Options 可以來自任何地方。當使用者可能對你的程式只能藉由 command line 輸入感到不滿，妳/你很快就會用到 config file 或是 environment variables 了。這些都可以幾乎無痛得透過 Boost.Program_options 來擴充。 &lt;/li&gt; &lt;/ul&gt;  &lt;h1&gt;Tutorial&lt;/h1&gt;  &lt;p&gt;在這個 section ，我們將從最簡單的地方開始，之後逐漸知道大部分 Boost.Program_options 的 usage scenarios 。這部份的文件都只有部份的、重要的程式碼，完整的範例可以在：&lt;/p&gt;  &lt;pre class="brush: bash;"&gt;BOOST_ROOT/libs/program_options/example&lt;/pre&gt;

&lt;p&gt;資料夾找到。此外整個範例，都假設下面的 namesapce alias 是有效的！&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;namespace po = boost::program_options&lt;/pre&gt;

&lt;h2&gt;Getting Started&lt;/h2&gt;

&lt;p&gt;第一個也可能是最簡單的一個範例是：&lt;/p&gt;

&lt;p&gt;處理兩個 options&lt;/p&gt;

&lt;p&gt;下面是程式碼部份（完整程式可以在 example/first.cpp 找到）&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;// Declare the supported options.
po::options_description desc(&amp;quot;Allowed options&amp;quot;);
desc.add_options()
    (&amp;quot;help&amp;quot;, &amp;quot;produce help message&amp;quot;)
    (&amp;quot;compression&amp;quot;, po::value&amp;lt;int&amp;gt;(), &amp;quot;set compression level&amp;quot;)
;&lt;/pre&gt;

&lt;p&gt;一開始的地方宣告了一個 &lt;a href="http://www.boost.org/doc/libs/1_39_0/doc/html/boost/program_options/options_description.html" target="_blank"&gt;options_descriptions&lt;/a&gt; 來存放允許的 options。呼叫 options_description class 的 &lt;font color="#0080ff"&gt;add_options&lt;/font&gt; method 會回傳一個提供了 &lt;font color="#0080ff"&gt;operator()&lt;/font&gt; 操作的 proxy object 。呼叫 operator() 就是宣告了 options 。參數分別是：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;(option name, information about value, option description)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;這個範例裡頭，第一個 option 沒有 value，第二個 options 有一個型別是 int 的 value 。&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;po::variables_map vm;
po::store(po::parse_command_line(ac, av, desc), vm);
po::notify(vm);    &lt;/pre&gt;

&lt;p&gt;之後，宣告一個型別為 &lt;font color="#0080ff"&gt;variables_map&lt;/font&gt; 的 object -- vm。variables_map 是用來存放任意型別的 value 。接著呼叫：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;store &lt;/li&gt;

  &lt;li&gt;parse_command_line &lt;/li&gt;

  &lt;li&gt;notify &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;去讓 vm 獲得所有 command line 來的 value。&lt;/p&gt;

&lt;pre class="brush: cpp;"&gt;if (vm.count(&amp;quot;help&amp;quot;)) {
    cout &amp;lt;&amp;lt; desc &amp;lt;&amp;lt; &amp;quot;\n&amp;quot;;
    return 1;
}

if (vm.count(&amp;quot;compression&amp;quot;)) {
    cout &amp;lt;&amp;lt; &amp;quot;Compression level was set to &amp;quot; 
 &amp;lt;&amp;lt; vm[&amp;quot;compression&amp;quot;].as&amp;lt;int&amp;gt;() &amp;lt;&amp;lt; &amp;quot;.\n&amp;quot;;
} else {
    cout &amp;lt;&amp;lt; &amp;quot;Compression level was not set.\n&amp;quot;;
}&lt;/pre&gt;

&lt;p&gt;最後我們可以任意地使用 options 了，variable_map 提供了像是 std::map 的操作，除了取得 value 時，必須使用 &lt;font color="#0080ff"&gt;as&lt;/font&gt; method外。（要是你不小心誤用了 as 中的型別參數，使得 as 參數想取出的型別和實際不合時，會出一個 exception）&lt;/p&gt;

&lt;p&gt;試著 compile 你的程式吧，下面是個範例：&lt;/p&gt;

&lt;pre class="brush: bash;"&gt;$bin/gcc/debug/first
Compression level was not set.
$bin/gcc/debug/first --help
Allowed options:
  --help                 : produce help message
  --compression arg      : set compression level
$bin/gcc/debug/first --compression 10
Compression level was set to 10.&lt;/pre&gt;

&lt;h2&gt;Reference&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Boost 1.39.0 Doc: &lt;a href="http://www.boost.org/doc/libs/1_39_0/doc/html/program_options.html" target="_blank"&gt;Chapter 13. Boost.Program_options&lt;/a&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;See Also&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href="http://keikoblog.blogspot.com/2009/08/boostprogramoptions-tutorial-option.html" target="_blank"&gt;Boost.Program_options – Option Details and Multiple Sources&lt;/a&gt; &lt;/li&gt;
&lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-4806787934695446527?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/4806787934695446527/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=4806787934695446527' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4806787934695446527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4806787934695446527'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/08/boostprogramoptions-introduction-and.html' title='Boost.Program_options – Introduction and Tutorial'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-1759856720323960496</id><published>2009-07-25T01:32:00.001+08:00</published><updated>2009-07-25T01:32:07.535+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Server Host'/><title type='text'>浮動 IP 架站</title><content type='html'>&lt;p&gt;幾經波折，還是決定自己來架設一台 server ，用的是陪我走過大學研究所六年的電腦，七年了，七年之癢了，換了新電腦，就拿來當 server 吧～家裏用的是沒有固定 IP 的 ADSL，於是去 &lt;a href="http://www.dyndns.com/" target="_blank"&gt;DynDNS&lt;/a&gt; 申請了個免費帳號。不過因為是免費的，domain name 的名字不是那麼自由，就像這篇&lt;a href="http://mtbook.net/mtbook_domain.html" target="_blank"&gt;教學文&lt;/a&gt;所說的：想要得到 *.tw 結尾的網址要付錢，而且只有 *.idv.tw 比較便宜，*.net.tw 或 *.org.tw 等都不是那麼容易，除非執念太深，不然使用推薦使用 &lt;a href="http://www.dyndns.com/" target="_blank"&gt;DynDNS&lt;/a&gt; 這類免費的服務，有些名字還至於太糟。&lt;/p&gt;  &lt;h1&gt;   &lt;p&gt;申請 DynDNS&lt;/p&gt; &lt;/h1&gt;  &lt;p&gt;到 &lt;a title="https://www.dyndns.com/" href="https://www.dyndns.com/"&gt;https://www.dyndns.com/&lt;/a&gt; 後，按下網頁右上角的 Create Account 就可以申請帳號了。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/Smnv8l2u4jI/AAAAAAAAAjE/U6mTPsElx60/s1600-h/image%5B3%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="477" alt="image" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/Smnv-zLAOrI/AAAAAAAAAjI/GiJOnWFD5-g/image_thumb%5B1%5D.png?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;有了帳號後，還需要一個小程式，讓它常駐在系統裡，當 ADSL 撥接上後就可以自動連接到 DynDNS 去更新 IP 與 domain 的對應。 &lt;/p&gt;  &lt;h2&gt;Windows &lt;/h2&gt;  &lt;p&gt;在 Windows 上可以用DynDNS Updater: &lt;a title="http://cdn.dyndns.com/windows/DynUpSetup.exe" href="http://cdn.dyndns.com/windows/DynUpSetup.exe"&gt;http://cdn.dyndns.com/windows/DynUpSetup.exe&lt;/a&gt; 提供的工具，相當不傷腦又好用。&lt;/p&gt;  &lt;h2&gt;Linux &lt;/h2&gt;  &lt;p&gt;稍稍麻煩了點，需要 ddclient 這程式，主流的 distribution 都可以用套件管理程式取得，或是到&lt;a href="http://ddclient.wiki.sourceforge.net/" target="_blank"&gt;這邊&lt;/a&gt;來下載。ddclient 的設定檔放在 /etc/ddclient.conf 下，網路上有很多教學，指導怎麼寫這設定檔，但最方便莫過於使用 &lt;a href="http://www.dyndns.com/" target="_blank"&gt;DynDNS&lt;/a&gt; 提供的 config file generator 了。登入 DynDNS 後，點選 &lt;a title="https://www.dyndns.com/support/tools/clientconfig.html" href="https://www.dyndns.com/support/tools/clientconfig.html"&gt;https://www.dyndns.com/support/tools/clientconfig.html&lt;/a&gt; 這網址，就會看到下方的頁面，選擇你要產生的 domain 和工具類型即可。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/SmnwAWU2sFI/AAAAAAAAAjM/4hi7bZAPabU/s1600-h/image%5B9%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="272" alt="image" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/SmnwCEziJMI/AAAAAAAAAjQ/47LfJZkUSFQ/image_thumb%5B5%5D.png?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;下面就是產生的設定檔，比起網路上有得教學和既有設定簡潔許多。&lt;/p&gt;  &lt;pre class="brush: bash;"&gt;## ddclient configuration file
daemon=600                  # check every 600 seconds
syslog=yes                  # log update msgs to syslog
mail-failure=keiko.zhou@gmail.com # Mail failed updates to user
pid=/var/run/ddclient.pid   # record PID in file.

## Detect IP with our CheckIP server
use=web, web=checkip.dyndns.com/, web-skip='IP Address'

## DynDNS username and password here
login=Keiko
password=##YOUR PASSWORD##

## Default options
protocol=dyndns2
server=members.dyndns.org

## Dynamic DNS hosts
keiko.homelinux.net&lt;/pre&gt;

&lt;p&gt;根據&lt;a href="http://gisanfu.pixnet.net/blog/post/5559784" target="_blank"&gt;好心人&lt;/a&gt;提示，為防萬一，第一次使用 ddclient 時，建議可以用 debug mode ，確定設定檔行不行得通。&lt;/p&gt;

&lt;pre class="brush: bash;"&gt;ddclient -daemon=0 -debug -verbose -noquiet&lt;/pre&gt;

&lt;p&gt;成功啟動的話，會看到類似下圖的畫面。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/SmnwDrNj0FI/AAAAAAAAAjU/KQ_1lL37aA8/s1600-h/image%5B17%5D.png"&gt;&lt;img title="HostYourServer03" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="265" alt="HostYourServer03" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/SmnwFc0Wh4I/AAAAAAAAAjY/1157XSOj64c/HostYourServer03%5B3%5D.jpg?imgmax=800" width="644" border="0" /&gt; 

    &lt;br /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-1759856720323960496?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/1759856720323960496/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=1759856720323960496' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/1759856720323960496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/1759856720323960496'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/07/ip.html' title='浮動 IP 架站'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_2ZMoTkLFVu8/Smnv-zLAOrI/AAAAAAAAAjI/GiJOnWFD5-g/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-2703562014080184922</id><published>2009-06-11T23:30:00.001+08:00</published><updated>2009-06-11T23:30:10.227+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>學長，我錯了…</title><content type='html'>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;星期一跟小路學長吃飯才聊到某某人好像到了某校畢業典禮講了不恰當的話，沒想到今天回家我弟興致高昂地跑來叫我去參加反奴隸銀行遊行，順便問我認不認識楊基寬，還說這人大學跟我同間…&lt;/p&gt;  &lt;p&gt;好吧，那就仔細來看一下，哇，ptt 好多懶人包，學校還發了&lt;a href="http://news.secr.ncku.edu.tw/files/16-1054-54092.php" target="_blank"&gt;新聞稿&lt;/a&gt;：&lt;/p&gt;  &lt;p&gt;第一點，給選擇延畢學生的提醒，如果你是因為景氣風暴而決定在校園裡面多躲一年的話，但請你告訴自己，職場是你人生必經的路，你沒有任何閃躲的空間，&lt;font color="#0080ff"&gt;如果你的生平第一次就當個躲起來的懦夫，那麼你還能指望有什麼擔當呢？&lt;/font&gt;成大的學生不應該如此。&lt;/p&gt;  &lt;p&gt;第二點，給選擇讀研究所同學的一個提醒，如果你讀研究所的出發點，是希望你將來的薪水會比學士要高一點，碩士的名聲聽起來會比學士要好一點，那麼整個社會，對於一個心中只是想著多賺幾塊錢及虛榮心作祟的碩士生，還能期望他什麼呢，社會指望你讀研究所是希望你論文的研究主題能為社會或產業解決某一個學士生無法解決的問題，而不是&lt;font color="#0080ff"&gt;指望你拿一篇長篇大論甚至是廢話連篇的論文來滿足你個人狹隘的虛榮心和薪水的要求&lt;/font&gt;，因此請告訴自己，職場是你人生必經的路，如果你生平第一次就只能這麼狹隘的自我期許，那麼你能夠指望這個狹隘的主人，就是你，會有什麼擔當呢？成大的學生不應該如此。&lt;/p&gt;  &lt;p&gt;第三點，是給選擇就業的同學一個提醒，我有信心學弟妹們都能順利找到工作，但因為今年景氣比較特殊，如果不幸的在未來，你已經不眠不休努力找工作找了三個月，還沒有找到的話，那麼請試著採用學長要給各位的一個策略，叫做「勇者策略」，當我們剛畢業的時候，什麼都還不會的時候，我們需要爭取的不是薪資，我們需要爭取的不是公司的大小，我們需要爭取的不是公司離家近不近，我們需要爭取的不是公司有沒有某一項的福利，我們需要爭取的不是公司需不需要加班，我們唯一需要爭取的就是那最珍貴的磨練，還有證明自己的機會，因此&lt;font color="#0080ff"&gt;所謂的勇者策略是，當你經過3個月都還不能找到工作的時候，請挑選一家你心目中的公司，仔細研究這家公司有什麼地方是你可以為他們帶來所需要的解決提案，然後西裝筆挺的走進那家公司，眼神正視老闆跟他講說：「老闆，我這裡有一個針對貴公司某產品的提案，我願意不拿薪水，為公司效勞，直到景氣恢復為止。」&lt;/font&gt;老闆問你為什麼，你就跟他講，因為我需要磨練，我需要向你證明我是有用的，半年後如果景氣恢復，那麼老闆肯定會先用你，因為企業看到了你的主動，因為企業看到了你的解決能力，因為企業看到了你當仁不讓的決心，屆時你的經驗超過那些空等待的同學。&lt;/p&gt;  &lt;p&gt;ㄜ…&lt;/p&gt;  &lt;p&gt;第一點好像太偏頗了、第二點好像太偏激、第三點…… 聽說前陣子 Google/MS 人事凍結，早知道我就 xxoo &lt;/p&gt;  &lt;p&gt;想起星期天跟老師聚餐，老師講的話：要是我們的教育，得讓孩子這麼辛苦，我們的教育是失敗的…&lt;/p&gt;  &lt;p&gt;ps. 打開 WLW 又寫不出東西了，五月都沒寫 blog ，忘了怎麼寫文章了，看來我也要找個作文老師了！&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-2703562014080184922?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/2703562014080184922/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=2703562014080184922' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/2703562014080184922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/2703562014080184922'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/06/blog-post.html' title='學長，我錯了…'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-5370769984101116809</id><published>2009-06-11T17:00:00.001+08:00</published><updated>2009-06-11T17:00:27.743+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Debugging'/><title type='text'>啟動完整的記憶體傾印 Enable Complete Memory Dump</title><content type='html'>&lt;p&gt;一直困擾我的問題，沒想到今天終於得到解答，感謝不知名的強者我同事！&lt;/p&gt;  &lt;p&gt;為了讓系統 crash 後有較多的資訊可以幫助 debug ，我們可以設定系統將 dump 資訊盡可能的保留下來，方法很簡單，進到&lt;font color="#0080ff"&gt;啟動及修復&lt;/font&gt;後，選擇&lt;font color="#0080ff"&gt;撰寫偵錯資訊（write debugging information）&lt;/font&gt;，不過有時會發現找不到&lt;font color="#0080ff"&gt;完整的記憶體傾印（Complete Memory Dump）&lt;/font&gt;的選項，即使是將在將虛擬記憶體調大、實際環境的硬碟空間也足夠的情況下依然會有這種情形出現。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/SjDHkABFuGI/AAAAAAAAAio/_zF3DqEy9WM/s1600-h/CompleteMemoryDump%5B10%5D.jpg"&gt;&lt;img title="CompleteMemoryDump" style="border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; border-left: 0px; margin-right: auto; border-bottom: 0px" height="428" alt="CompleteMemoryDump" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/SjDHlY9GD6I/AAAAAAAAAis/Ye8mGRjYxaM/CompleteMemoryDump_thumb%5B6%5D.jpg?imgmax=800" width="364" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;此時需要修改一個 registry key 來啟動，&lt;font color="#0080ff"&gt;\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\CrashControl\CrashDumpEnabled&lt;/font&gt; 從 &lt;font color="#ff0000"&gt;2 改成 1&lt;/font&gt;。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/SjDHmiiYXaI/AAAAAAAAAiw/75wJbHia1_0/s1600-h/CompleteMemoryDump06%5B10%5D.jpg"&gt;&lt;img title="CompleteMemoryDump06" style="border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; border-left: 0px; margin-right: auto; border-bottom: 0px" height="339" alt="CompleteMemoryDump06" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/SjDHn6zvzhI/AAAAAAAAAi0/gpJU0jBAN2o/CompleteMemoryDump06_thumb%5B6%5D.jpg?imgmax=800" width="724" border="0" /&gt;&lt;/a&gt; 再回到&lt;font color="#0080ff"&gt;啟動及修復&lt;/font&gt;後，選擇&lt;font color="#0080ff"&gt;撰寫偵錯資訊（write debugging information）&lt;/font&gt;就會出現&lt;font color="#0080ff"&gt;完整的記憶體傾印（Complete Memory Dump）&lt;/font&gt;的選項。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/SjDHpOYOKTI/AAAAAAAAAi4/pIuPamQ-zLw/s1600-h/CompleteMemoryDump07%5B4%5D.jpg"&gt;&lt;img title="CompleteMemoryDump07" style="border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; border-left: 0px; margin-right: auto; border-bottom: 0px" height="428" alt="CompleteMemoryDump07" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/SjDHqjh2qQI/AAAAAAAAAi8/fdSUXpECxwA/CompleteMemoryDump07_thumb%5B2%5D.jpg?imgmax=800" width="364" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-5370769984101116809?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/5370769984101116809/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=5370769984101116809' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5370769984101116809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5370769984101116809'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/06/enable-complete-memory-dump.html' title='啟動完整的記憶體傾印 Enable Complete Memory Dump'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_2ZMoTkLFVu8/SjDHlY9GD6I/AAAAAAAAAis/Ye8mGRjYxaM/s72-c/CompleteMemoryDump_thumb%5B6%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-132831108072616194</id><published>2009-06-01T19:27:00.001+08:00</published><updated>2009-06-11T23:35:54.384+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='騰雲駕霧程式競賽'/><title type='text'>騰雲駕霧程式競賽 Blog 開跑了～</title><content type='html'>&lt;p align="center"&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/Sb53EcbII1I/AAAAAAAAAeI/DgZXzhi1xD8/s1600-h/image%5B6%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="278" alt="image" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/Sb53IJw77UI/AAAAAAAAAeM/HvqFmC3SPPI/image_thumb%5B2%5D.png?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.wretch.cc/blog/trendnop09" target="_blank"&gt;趨勢科技 2009 騰雲駕霧程式競賽的 blog&lt;/a&gt; 開跑了，就在&lt;a href="http://keikoblog.blogspot.com/2009/03/windows-debugging-kernel-debugging-with.html" target="_blank"&gt;作者&lt;/a&gt;外出到台南取材的時候 -_-||&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.wretch.cc/blog/trendnop09" href="http://www.wretch.cc/blog/trendnop09"&gt;http://www.wretch.cc/blog/trendnop09&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;上面可以詢問一切有關於比賽的問題，像是比賽方式、評分標準、今年還有沒有&lt;font color="#ff0000"&gt;妙齡&lt;/font&gt;小天使、 training course 可不可以&lt;font color="#ff0000"&gt;翹課&lt;/font&gt;、獎金可不可以不要&lt;font color="#ff0000"&gt;扣稅&lt;/font&gt;、決賽入闈可不可以帶&lt;font color="#ff0000"&gt;幸運毛毯&lt;/font&gt;、頒獎典禮可不可以帶&lt;font color="#ff0000"&gt;寵物&lt;/font&gt;等等。不過還是要 prompt &lt;a href="http://keikoblog.blogspot.com" target="_blank"&gt;本站&lt;/a&gt;一下，所以要是大家在&lt;a href="http://www.wretch.cc/blog/trendnop09" target="_blank"&gt;官方 blog&lt;/a&gt; 問不到滿意的答案，歡迎還是回（娘家？！）到這發問啊，代客詢問是我專業自婊、出一張嘴、毀人不倦之外的第四專長，我會秉持打破沙鍋問到底、一審不定讞、二審再上訴、三審就辭職的態度幫忙發問，下面開放十個回應免費匿名…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-132831108072616194?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/132831108072616194/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=132831108072616194' title='9 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/132831108072616194'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/132831108072616194'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/03/blog_16.html' title='騰雲駕霧程式競賽 Blog 開跑了～'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_2ZMoTkLFVu8/Sb53IJw77UI/AAAAAAAAAeM/HvqFmC3SPPI/s72-c/image_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-2141177762354110378</id><published>2009-06-01T19:27:00.000+08:00</published><updated>2009-06-11T23:34:07.564+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>騰雲駕霧程式競賽</title><content type='html'>&lt;p&gt; 這當然是廣告文！&lt;/p&gt;  &lt;p&gt;我們公司辦的比賽，有興趣的學長弟妹可以參加唷！節錄一些重點：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;「騰雲駕霧程式競賽」由趨勢科技主辦，IBM生物資訊研發中心協辦，該單位將提供硬體設備贊助。競賽籌備小組自3月10日起將至台北科大、台大、清大、交大等9所大專院校進行巡迴說明…&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;哈，漏掉成大了，不過 &lt;font color="#ff0000"&gt;3/24(二)&lt;/font&gt; 還是會去成大資工 4263 宣傳，可能過一陣子，海報、文宣就會出來了，&lt;font color="#0000ff"&gt;我也會去唷，大家再找時間吃個飯吧！&amp;#160; &amp;lt;--- 重點！&lt;/font&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;報名資格      &lt;br /&gt;大學生、研究生、每隊&lt;font color="#ff0000"&gt;四人&lt;/font&gt;（不多不少唷），可跨校！ &lt;/li&gt;    &lt;li&gt;報名      &lt;br /&gt;3/20-5/15：將開放網路報名，6月份將安排參賽者接受第一階段的網路遠距教學！ &lt;/li&gt;    &lt;li&gt;比賽方式      &lt;ul&gt;       &lt;li&gt;初賽          &lt;br /&gt;7/1：網路公佈題目。           &lt;br /&gt;7/8：00:00 停止收件。           &lt;br /&gt;7/22：公佈入圍名單。 &lt;/li&gt;        &lt;li&gt;決賽訓練課程          &lt;br /&gt;7/30 ~ 7/31：到趨勢上課！ &lt;/li&gt;        &lt;li&gt;決賽          &lt;br /&gt;8/18 ~ 8/19：決賽入圍。今年也有可能不會在台北士林劍潭青年活動中心，會改去 IBM 生物資訊研發中心吧？機器都在那邊，或是要很炫的自己遠端 deploy 到伺服器海中，那就不必到現場了！ &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;頒獎      &lt;br /&gt;8/20：頒獎。往年頒獎典禮都蠻有心的，會找飯店，以前有去過晶華酒店，典禮有簡單的點心、可邀請家人朋友、找記者來採訪（不過記者好像都不會來-_-|） &lt;/li&gt;    &lt;li&gt;獎項（這好像是最重要的）      &lt;br /&gt;1st：NT$500,000       &lt;br /&gt;2nd：NT$300,000       &lt;br /&gt;3rd：NT$200,000       &lt;br /&gt;4th：NT$150,000       &lt;br /&gt;5th：NT$100,000       &lt;br /&gt;6th ~ 10th：NT$50,000       &lt;br /&gt;&lt;font color="#ff0000"&gt;預聘書現在只給前三名了&lt;/font&gt; &amp;lt;囧&amp;gt; &lt;/li&gt;    &lt;li&gt;題目      &lt;br /&gt;好像沒提到，但是跟雲端運算有關就是！ &lt;/li&gt;    &lt;li&gt;競賽網站      &lt;br /&gt;&lt;a title="http://www.trend.org/fd/tabid/66/Default.aspx" href="http://www.trend.org/fd/tabid/66/Default.aspx"&gt;http://www.trend.org/fd/tabid/66/Default.aspx&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;附註      &lt;br /&gt;比賽中會需要各式各樣的人，寫 UI、寫程式、寫文件、上台 presentation、找 bug、做 testing 都會，所以記得要把團隊技能平均問題，不要只點某一、兩樣技能唷！ &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;我是工作人員，不管有什麼疑難雜症、難以啟齒需要匿名的問題，我都可以代為傳達唷！&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-2141177762354110378?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/2141177762354110378/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=2141177762354110378' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/2141177762354110378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/2141177762354110378'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/03/blog-post_05.html' title='騰雲駕霧程式競賽'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-351010210714145833</id><published>2009-05-01T19:27:00.000+08:00</published><updated>2009-06-11T23:39:39.905+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='騰雲駕霧程式競賽'/><title type='text'>騰雲駕霧程式競賽</title><content type='html'>&lt;p align="center"&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/SbZXl9BKrwI/AAAAAAAAAeA/Dvq399O47oM/s1600-h/DM01%5B4%5D.jpg"&gt;&lt;font color="#494949"&gt;沒想到真的有人來問問題，作一篇置底廣告文，歡迎大家提出問題！&lt;/font&gt;&lt;img title="DM01" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="772" alt="DM01" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/SbZXn_TzyaI/AAAAAAAAAeE/ROdWx6Ye8-A/DM01_thumb%5B2%5D.jpg?imgmax=800" width="536" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;我們公司辦的比賽，有興趣的人，尤其是學長弟妹可以參加唷！節錄一些重點：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;「騰雲駕霧程式競賽」由趨勢科技主辦，IBM生物資訊研發中心協辦，該單位將提供硬體設備贊助。競賽籌備小組自3月10日起將至台北科大、台大、清大、交大等9所大專院校進行巡迴說明…&lt;/p&gt; &lt;/blockquote&gt;  &lt;ul&gt;   &lt;li&gt;說明會時間地點      &lt;br /&gt;      &lt;table cellspacing="0" cellpadding="2" width="423" border="0"&gt;&lt;tbody&gt;         &lt;tr&gt;           &lt;td valign="top" width="197"&gt;時間&lt;/td&gt;            &lt;td valign="top" width="82"&gt;學校&lt;/td&gt;            &lt;td valign="top" width="142"&gt;地點&lt;/td&gt;         &lt;/tr&gt;          &lt;tr&gt;           &lt;td valign="top" width="197"&gt;3/11(二) 12:20-13:30&lt;/td&gt;            &lt;td valign="top" width="82"&gt;北科大&lt;/td&gt;            &lt;td valign="top" width="142"&gt;綜合科館第三演講廳&lt;/td&gt;         &lt;/tr&gt;          &lt;tr&gt;           &lt;td valign="top" width="197"&gt;3/11(三) 13:00-14:00&lt;/td&gt;            &lt;td valign="top" width="82"&gt;台大&lt;/td&gt;            &lt;td valign="top" width="142"&gt;資工系 102&lt;/td&gt;         &lt;/tr&gt;          &lt;tr&gt;           &lt;td valign="top" width="197"&gt;3/12(四) 12:10-13:20&lt;/td&gt;            &lt;td valign="top" width="82"&gt;台科大&lt;/td&gt;            &lt;td valign="top" width="142"&gt;IB510&lt;/td&gt;         &lt;/tr&gt;          &lt;tr&gt;           &lt;td valign="top" width="197"&gt;3/16(一) 12:20-13:30&lt;/td&gt;            &lt;td valign="top" width="82"&gt;中山&lt;/td&gt;            &lt;td valign="top" width="142"&gt;電資大樓 F1001&lt;/td&gt;         &lt;/tr&gt;          &lt;tr&gt;           &lt;td valign="top" width="197"&gt;3/17(二) 11:00-12:00&lt;/td&gt;            &lt;td valign="top" width="82"&gt;中央&lt;/td&gt;            &lt;td valign="top" width="142"&gt;工五館 207&lt;/td&gt;         &lt;/tr&gt;          &lt;tr&gt;           &lt;td valign="top" width="197"&gt;3/18(三) 15:00-16:00&lt;/td&gt;            &lt;td valign="top" width="82"&gt;清大&lt;/td&gt;            &lt;td valign="top" width="142"&gt;資電館 127&lt;/td&gt;         &lt;/tr&gt;          &lt;tr&gt;           &lt;td valign="top" width="197"&gt;3/19(四) 12:20-13:30&lt;/td&gt;            &lt;td valign="top" width="82"&gt;交大&lt;/td&gt;            &lt;td valign="top" width="142"&gt;工三 122&lt;/td&gt;         &lt;/tr&gt;          &lt;tr&gt;           &lt;td valign="top" width="197"&gt;3/23(一) 14:00-16:00&lt;/td&gt;            &lt;td valign="top" width="82"&gt;中正&lt;/td&gt;            &lt;td valign="top" width="142"&gt;地震館 215&lt;/td&gt;         &lt;/tr&gt;          &lt;tr&gt;           &lt;td valign="top" width="197"&gt;3/24(二) 12:20-13:30&lt;/td&gt;            &lt;td valign="top" width="82"&gt;成大&lt;/td&gt;            &lt;td valign="top" width="142"&gt;成大資工 4263&lt;/td&gt;         &lt;/tr&gt;       &lt;/tbody&gt;&lt;/table&gt;   &lt;/li&gt;    &lt;li&gt;報名資格      &lt;br /&gt;大學生、研究生、每隊&lt;font color="#ff0000"&gt;四人&lt;/font&gt;（不多不少唷），可跨校！ &lt;/li&gt;    &lt;li&gt;報名      &lt;br /&gt;&lt;font color="#ff0000"&gt;3/20-5/15：將開放網路報名&lt;/font&gt;，6月份將安排參賽者接受第一階段的網路遠距教學！ &lt;/li&gt;    &lt;li&gt;比賽方式      &lt;ul&gt;       &lt;li&gt;初賽          &lt;br /&gt;7/1：網路公佈題目。           &lt;br /&gt;7/8：00:00 停止收件。           &lt;br /&gt;7/22：公佈入圍名單。 &lt;/li&gt;        &lt;li&gt;決賽訓練課程          &lt;br /&gt;7/30 ~ 7/31：到趨勢上課！ &lt;/li&gt;        &lt;li&gt;決賽          &lt;br /&gt;8/18 ~ 8/19：決賽入圍。今年也有可能不會在台北士林劍潭青年活動中心，會改去 IBM 生物資訊研發中心吧？機器都在那邊，或是要很炫的自己遠端 deploy 到伺服器海中，那就不必到現場了！ &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;頒獎      &lt;br /&gt;8/20：頒獎。往年頒獎典禮都蠻有心的，會找飯店，以前有去過晶華酒店，典禮有簡單的點心、可邀請家人朋友、找記者來採訪（不過記者好像都不會來-_-|） &lt;/li&gt;    &lt;li&gt;獎項（這好像是最重要的）      &lt;br /&gt;1st：NT$500,000       &lt;br /&gt;2nd：NT$300,000       &lt;br /&gt;3rd：NT$200,000       &lt;br /&gt;4th：NT$150,000       &lt;br /&gt;5th：NT$100,000       &lt;br /&gt;6th ~ 10th：NT$50,000       &lt;br /&gt;&lt;font color="#ff0000"&gt;預聘書現在只給前三名了&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;題目      &lt;br /&gt;好像沒提到，但是跟雲端運算有關就是！ &lt;/li&gt;    &lt;li&gt;競賽網站      &lt;br /&gt;&lt;a title="http://www.trend.org/fd/tabid/66/Default.aspx" href="http://www.trend.org/fd/tabid/66/Default.aspx"&gt;http://www.trend.org/fd/tabid/66/Default.aspx&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;附註      &lt;br /&gt;比賽中會需要各式各樣的人，寫 UI、寫程式、寫文件、上台 presentation、找 bug、做 testing 都會，所以記得要把團隊技能平均問題，不要只點某一、兩樣技能唷！ &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;我是工作人員，不管有什麼疑難雜症、難以啟齒需要匿名的問題，我都可以代為傳達唷！&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-351010210714145833?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/351010210714145833/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=351010210714145833' title='8 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/351010210714145833'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/351010210714145833'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/03/blog-post_10.html' title='騰雲駕霧程式競賽'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_2ZMoTkLFVu8/SbZXn_TzyaI/AAAAAAAAAeE/ROdWx6Ye8-A/s72-c/DM01_thumb%5B2%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-4162458188572007008</id><published>2009-04-25T23:14:00.001+08:00</published><updated>2009-04-25T23:14:23.664+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><title type='text'>How to Deploy my Visual C++ Applications, Part 1</title><content type='html'>&lt;h3&gt;前言&lt;/h3&gt;  &lt;p&gt;寫程式的人常常會寫了一些應用程式或小工具後，想把它拿到另外一台電腦上測試或是分享給親朋好友，此時若是對方的電腦沒有安裝 Visual Studio，往往會遇到一個問題：對方無法執行我們的程式！&lt;/p&gt;  &lt;p&gt;中文版錯誤訊息：&lt;img title="ScreenHunter_02 Apr. 25 20.41" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="135" alt="ScreenHunter_02 Apr. 25 20.41" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/SfMorDEenyI/AAAAAAAAAhk/x_VigwEVkGs/ScreenHunter_02%20Apr.%2025%2020.41_thumb%5B2%5D.jpg?imgmax=800" width="595" border="0" /&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;無法啟動這個應用程式，因為應用程式的設定不正確。重新安裝應用程式應該可以修復這個問題。&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;英文版錯誤訊息：（我沒有英文版 Windows ，只好&lt;a href="http://forum.notebookreview.com/showthread.php?t=144783&amp;amp;page=54" target="_blank"&gt;上網偷&lt;/a&gt;）&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/SfMor7XIJyI/AAAAAAAAAho/MKquhUwuRQ4/s1600-h/ScreenHunter_01%20Apr.%2025%2022.11%5B6%5D.jpg"&gt;&lt;img title="ScreenHunter_01 Apr. 25 22.11" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="119" alt="ScreenHunter_01 Apr. 25 22.11" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/SfMossuR1OI/AAAAAAAAAhs/2jn18MO2JYI/ScreenHunter_01%20Apr.%2025%2022.11_thumb%5B4%5D.jpg?imgmax=800" width="500" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem. &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;每當我遇到這種情況的時候，我都會想起研究所的學弟 DNA ！當然不是想他這個人，是想起他說的話：&lt;/p&gt;  &lt;p&gt;What The Fuck! (WTF)&lt;/p&gt;  &lt;p&gt;這當然有一些解決方式：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;static link、 &lt;/li&gt;    &lt;li&gt;找出所有的 dependency ，然後包一包丟過去、 &lt;/li&gt;    &lt;li&gt;做個 release build ，然後找 MS 出的轉散發套件（redistributable package）請對方安裝、 &lt;/li&gt;    &lt;li&gt;做個安裝程式，把所有東西包一包！ &lt;/li&gt; &lt;/ol&gt;  &lt;h3&gt;解決方式&lt;/h3&gt;  &lt;p&gt;這裡就介紹最簡單的解決方式：copy！Visual C++ 的散佈套件放在：&lt;/p&gt;  &lt;p&gt;安裝目錄\VC\redist &lt;/p&gt;  &lt;p&gt;若是散佈 release 版本，就在這資料夾下根據平台選擇，若是 debug 版本，就選擇 Debug_NonRedist 這個子目錄，進去後一樣根據平台選擇下一個目錄。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/SfMotUPe8JI/AAAAAAAAAhw/wtj6lZnw_B0/s1600-h/image%5B3%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="256" alt="image" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/SfMouBwAhRI/AAAAAAAAAh0/DanTXHDtTFM/image_thumb%5B1%5D.png?imgmax=800" width="433" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;不論是 release 版或是 debug 版，目錄都會根據函式庫類型分類好，不過 debug 似乎比 release 少了些東西：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Microsoft.VC80.ATL &lt;/li&gt;    &lt;li&gt;Microsoft.VC80.MFCLOC &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;不確定是不是因為 debug 版沒有上面兩者或是包含在 DebugMFC 裡頭了&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/SfMouzUGL0I/AAAAAAAAAh4/-Dlm-ijDvPc/s1600-h/ScreenHunter_03%20Apr.%2025%2022.27%5B9%5D.jpg"&gt;&lt;img title="ScreenHunter_03 Apr. 25 22.27" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="200" alt="ScreenHunter_03 Apr. 25 22.27" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/SfMovtLe-hI/AAAAAAAAAh8/rhrvi-pQskE/ScreenHunter_03%20Apr.%2025%2022.27_thumb%5B5%5D.jpg?imgmax=800" width="364" border="0" /&gt;&lt;/a&gt; Microsoft Visual Studio 8\VC\redist\Debug_NonRedist\x86 的 layout，給 debug build 用&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/SfMowRyN49I/AAAAAAAAAiA/8EqY42qAnuc/s1600-h/ScreenHunter_04%20Apr.%2025%2022.27%5B8%5D.jpg"&gt;&lt;img title="ScreenHunter_04 Apr. 25 22.27" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="238" alt="ScreenHunter_04 Apr. 25 22.27" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/SfMoxKNJ_rI/AAAAAAAAAiE/Kyuz4RgkVtU/ScreenHunter_04%20Apr.%2025%2022.27_thumb%5B4%5D.jpg?imgmax=800" width="364" border="0" /&gt;&lt;/a&gt;Microsoft Visual Studio 8\VC\redist\x86 的 layout，給 release build 用&lt;/p&gt;  &lt;p&gt;剩下要做的就是把跟你程式相關的函式庫一同 copy 給對方就可以了，不過這只解決了與 Visual C++ 相關的相依性，其他的程式用到的函式庫，就得靠自己尋找一下。&lt;/p&gt;  &lt;p&gt;基於好奇，再往 CRT 的資料夾裡頭看一下，那麼你會發現裡頭有四個檔案：（節錄自&lt;a href="http://msdn.microsoft.com/en-us/library/abx4dbyh(VS.80).aspx" target="_blank"&gt;C Run-Time Library (CRT)&lt;/a&gt;）&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Microsoft.VC80.DebugCRT.manifest      &lt;br /&gt;Side-by-side assembly 不可或缺的一環，是微軟在 .Net 提出的架構，用來管理程式、元件的相依性。竟然說是不可或缺了，記得一定要 copy 這個檔案過去。 &lt;/li&gt;    &lt;li&gt;msvcr80d.dll      &lt;br /&gt;Multithreaded, dynamic link (import library for MSVCR80.DLL). Be aware that if you use the Standard C++ Library, your program will need MSVCP80.DLL to run.&lt;/li&gt;    &lt;li&gt;msvcp80d.dll      &lt;br /&gt;Standard C++ Library &lt;/li&gt;    &lt;li&gt;msvcm80d.dll      &lt;br /&gt;C Runtime import library. Used for mixed managed/native code. 如果程式沒用到 managed code，這個就不需要！&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/SfMox-y098I/AAAAAAAAAiI/GWvlzg1jsuY/s1600-h/image%5B8%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="223" alt="image" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/SfMozB7qW-I/AAAAAAAAAiM/7D9gZQIvAi0/image_thumb%5B4%5D.png?imgmax=800" width="364" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Reference&lt;/h3&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx" target="_blank"&gt;MSDN: How to: Deploy using XCopy&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/36971526-95f3-4a9f-a601-1843c86332c1" target="_blank"&gt;This application has failed to start because the application configuration is incorrect&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a title="MSDN: C Run-Time Library (CRT)" href="http://msdn.microsoft.com/en-us/library/abx4dbyh(VS.80).aspx" target="_blank"&gt;MSDN: C Run-Time Library (CRT)&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-4162458188572007008?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/4162458188572007008/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=4162458188572007008' title='5 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4162458188572007008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4162458188572007008'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/04/how-to-deploy-my-visual-c-applications.html' title='How to Deploy my Visual C++ Applications, Part 1'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_2ZMoTkLFVu8/SfMorDEenyI/AAAAAAAAAhk/x_VigwEVkGs/s72-c/ScreenHunter_02%20Apr.%2025%2020.41_thumb%5B2%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-1900777691951616057</id><published>2009-04-23T23:45:00.001+08:00</published><updated>2009-04-23T23:45:38.252+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>又是廣告，公司徵才！</title><content type='html'>&lt;p&gt;中午接到以前打工認識的朋友的電話，他現在在一間新公司上班，想在台灣成立軟體團隊，產品是 DVR 相關的監控產品，工作地點在台北中和或是大陸廣州中山，工作會用到 ARM, Linux, C/C++，職缺是軟韌體工程師，有熟悉下面的有加分：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;對 Video Codec （H.264）熟悉&lt;/li&gt;    &lt;li&gt;Video streaming&lt;/li&gt;    &lt;li&gt;TCP/UDP/RTP/RTSP protocol&lt;/li&gt;    &lt;li&gt;Linux kernel, driver&lt;/li&gt;    &lt;li&gt;Windows 遠端監控&lt;/li&gt;    &lt;li&gt;Mobile 遠端瀏覽程式&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;有興趣的朋友，可以跟我說唷！&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-1900777691951616057?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/1900777691951616057/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=1900777691951616057' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/1900777691951616057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/1900777691951616057'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/04/blog-post_23.html' title='又是廣告，公司徵才！'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-7323058348844177300</id><published>2009-04-12T10:39:00.001+08:00</published><updated>2009-04-12T10:39:33.256+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Qt'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><title type='text'>Qt 4.5 Released</title><content type='html'>&lt;p&gt;自從 Trolltech 被 Nokia 買了之後，網頁風格就變了，感覺好像比以前好了！不過最重要的是， Qt 4.5 改成以 LGPL 作為 Free 版本的授權，Yes！不過這次的編譯好像變麻煩了，試了好幾天 : ( 原來前陣子，這麼 down ，Qt 也要負責啦！）下面是嘗試過後，可用的編譯選項：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;configure &lt;font color="#ff0000"&gt;–platform win32-msvc&lt;/font&gt; –debug-and-release –no-qt3support &lt;font color="#ff0000"&gt;–no-webkit&lt;/font&gt;&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;-platfrom win32-msvc: 這似乎是這個版本一定要加的選項，我有試過用 %QMAKESPEC% 這個環境變數，但似乎沒用，一定得加這個選項。 &lt;/li&gt;      &lt;li&gt;-debug-and-release: 嗚嗚，是人總要 debug 吧，預設的編譯是不產生 debug 的，記得加上！ &lt;/li&gt;      &lt;li&gt;-no-qt3support: opensource 最常被訐詨的就是不向下相容， Qt 佛心來的！ &lt;/li&gt;      &lt;li&gt;-no-webkit: 論壇上很多人說他 build webkit 就會 build failed ，如果沒有要用到這個功能，可以略掉！不過我自己測試的結果是 OK！&lt;/li&gt;   &lt;/ul&gt;    &lt;li&gt;nmake&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;編譯環境：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Windows XP&lt;/li&gt;    &lt;li&gt;Visual Studio 2005 SP1&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Enjoy it!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-7323058348844177300?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/7323058348844177300/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=7323058348844177300' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/7323058348844177300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/7323058348844177300'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/04/qt-45-released.html' title='Qt 4.5 Released'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-4073520246736205371</id><published>2009-04-11T21:58:00.001+08:00</published><updated>2009-04-11T21:58:35.052+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Blog'/><title type='text'>PreCode Snippet 4.0.2 Released</title><content type='html'>&lt;p&gt;在之前的文章提到的 PreCode 出新版了，已經支援 SyntaxHighlighter 2.0 的語法。不必像&lt;a href="http://keikoblog.blogspot.com/2009/03/blog-syntaxhighlighter-precode.html" target="_blank"&gt;之前文章&lt;/a&gt;那樣進到原始碼模式修改 tag 。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-4073520246736205371?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/4073520246736205371/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=4073520246736205371' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4073520246736205371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4073520246736205371'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/04/precode-snippet-402-released.html' title='PreCode Snippet 4.0.2 Released'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-7979803065351213097</id><published>2009-04-06T23:20:00.001+08:00</published><updated>2009-04-06T23:26:33.496+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>喜形於色</title><content type='html'>&lt;p&gt;小學的時候大家都寫過國語習題的照樣造句，沒寫過的表示我們是不同年代的人了…&lt;/p&gt;  &lt;p&gt;今天我也要來照樣造句，&lt;/p&gt;  &lt;p&gt;第一題：喜形於色。    &lt;br /&gt;例句：小明的論文上了，所以喜形於色。     &lt;br /&gt;Keiko：Royce 今天喜形於色地丟著 msn 訊息！早上老闆看了都大叫：Royce 你在笑唷！晚上 Aawen 同事見了也大叫：Royce 你怎麼了，怎麼一直笑！&lt;/p&gt;  &lt;p&gt;第二題是成語造句，要先查成語字典，知道成語的意思後，再造句！    &lt;br /&gt;題目：春風得意。     &lt;br /&gt;解釋：舊時稱登進士第後的志得意滿為「春風得意」。後用以形容人做事順利，志得意滿的神情。唐˙孟郊˙登科後詩：「春風得意馬蹄疾，一日看盡長安花。」元˙喬吉˙金錢記˙第四折：「他見我春風得意長安道，因此上迎頭兒將女婿招。」     &lt;br /&gt;Keiko：今天台北冷冷的，飄著小雨，可是身邊暖暖地，原來旁邊站著是 Royce ，看他春風得意的，啊，原來台北沒有黃鶯，有的是路大師！原來人間四月天，春都到了小路身旁，怪不得外頭冷颼颼的，惟有這處暖！哇，春風滿面樂醄醄，一聲長笑海山高 : )&lt;/p&gt;  &lt;p&gt;第三題是自由發揮   &lt;br /&gt;題目：百年好合、永結同心    &lt;br /&gt;Keiko：老師，這題我要留到 5/17 ，口以嗎？    &lt;br /&gt;老師：可以啊，科科！&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-7979803065351213097?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/7979803065351213097/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=7979803065351213097' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/7979803065351213097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/7979803065351213097'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/04/blog-post_06.html' title='喜形於色'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-4534983732470650827</id><published>2009-04-02T23:58:00.001+08:00</published><updated>2009-04-02T23:58:23.300+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='研發替代役'/><title type='text'>當兵</title><content type='html'>&lt;p&gt;今天比平常早了一點到公司，就跟 Arther 老大閒聊了一下，聊到了成功嶺大專兵可能要又恢復了！夭壽啊，當兵耶，一個可以讓平常剛毅木訥、口才遲鈍的男人瞬間長舌的話題，就像瑪莉兄弟吃到無敵星星，講話、回憶技能都滿了！果不其然，坐我後頭的兩位 J 先生馬上就打開話夾子了，耶，Architect 的穩重怎麼都不見了！一個是步校、一個是帶預官的，還好不用一梯退三步，不然我就要站去 101 了！&lt;/p&gt;  &lt;p&gt;不過話題的結束台詞跟我想的一模一樣：   &lt;br /&gt;Jason 1：現在想想，當兵那段時間還蠻值得回憶的！    &lt;br /&gt;Jason 2：當兵是件可以回憶卻不想在經歷的事！    &lt;br /&gt;Keiko：Yes, bingo! （心理話）&lt;/p&gt;  &lt;p&gt;忘了自己哪時候退伍… &lt;/p&gt;  &lt;p&gt;啊，還有 866 天，這就是版面新工具的由來！&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-4534983732470650827?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/4534983732470650827/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=4534983732470650827' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4534983732470650827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4534983732470650827'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/04/blog-post.html' title='當兵'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-847303806978817410</id><published>2009-03-26T00:15:00.001+08:00</published><updated>2009-03-26T00:20:48.138+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='騰雲駕霧程式競賽'/><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>出差出差！</title><content type='html'>&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/ScpYmtAzgZI/AAAAAAAAAfw/P_9lRUn-NZI/s1600-h/wang0zc52.jpg"&gt;&lt;img title="wang0zc5" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="184" alt="wang0zc5" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/ScpYn5QndmI/AAAAAAAAAf0/A-FTZLFYmMA/wang0zc5_thumb.jpg?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;生平第一次出差，目的地是台南成大，南國的母校啊，真是令人懷念！雖然科技新貴已經是上個世紀的事了，但很多還是會把資訊系跟有錢畫上等號，殊不知成大資工系其實是個年輕到了不行的科系，沒有畢業校友的金錢挹注，換來的是古色古香的系館，儘管對這棟系館發出讚嘆的永遠外系的人多過在裡頭唸過的人…&lt;/p&gt;  &lt;p&gt;有種圍城的感覺：裡頭的人拼了命想外跑，外頭的人擠破頭想進來！好像選公司也是一樣的，永遠是還沒去過的公司最好！想起了跟 D.N.A 學弟講的話。&lt;/p&gt;  &lt;p&gt;Keiko：人家都學歷顯赫，個個都留美學歷！    &lt;br /&gt;D.N.A：可是你留台啊！開口粥，留台多年，菁英份子！&lt;/p&gt;  &lt;p&gt;哈哈，或許人就是這樣，對未知的東西不是充滿恐懼就是抱有美好幻想！忘了是哪位實驗室學長說過的話，還是我說得呢？&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;外國人絕對不會比較厲害，狗屁倒灶的事絕對比我們多又扯，只是我們只看到好的一面！&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;現在想想，我真應該在「工商服務時間」把這點提出來講一下！這就是所謂：門的另一端，真實的世界。突然想起上個禮拜請假到台南玩，星期一去了七股鹽田，在鹽山之前看到一對情侶朝我走來，男生是背對著我，手裡拿著相機，鏡頭當然對著心愛的女友，天空藍藍的，海風不強，輕輕拂過女孩的長髮，三千髮絲搖曳著，雖然只看到男生的背影，不過已經可以想像他是多麼小心翼翼想會這針對的一刻留下永恆的紀念，他一定小心翼翼地想捕捉女生最美的瞬間，傳說中甜蜜的青春也不過如此吧！&lt;/p&gt;  &lt;p&gt;可是呢？這當然是我的幻想啊，從來沒有女生讓我這樣拍過，我也沒有有錢到請 model 來讓我幻想一下，更何況我手中只有 Sony W7 這種傻到不行的相機！那現實可能是怎樣呢？&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;可能是男孩倒退著走，然後一個重心不穩，跌個狗吃屎。 &lt;/li&gt;    &lt;li&gt;也可能男生其實跟我一樣，得了一種「相機帕金森式症」，這是一種拿到相機才會發作，症狀是手晃不止的病。結果就是把女朋友拍得很醜，晚上回到飯店可能遭到一頓痛毆。 &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/ScpYo-mBncI/AAAAAAAAAf4/-m58Pywywe0/s1600-h/image%5B5%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="210" alt="image" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/ScpYqOlCFnI/AAAAAAAAAf8/Nn7cTC6kmKI/image_thumb%5B3%5D.png?imgmax=800" width="364" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;天啊，我話好多，讓我想起這幾天看的獵人漫畫 280 話的拿酷&lt;em&gt;&lt;/em&gt;戮，短短擦身而過，原來我也想了這麼多字！&lt;/p&gt;  &lt;p&gt;&lt;img title="its_Cold" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="100" alt="its_Cold" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/ScpYqpduxPI/AAAAAAAAAgA/hQBu3KLfGu0/its_Cold_thumb1.jpg?imgmax=800" width="100" border="0" /&gt;&lt;/p&gt;  &lt;p&gt;出差很累，比上班還累，早上六點半就起床，因為家住台北知名的塞車之地，天空下著小雨，冷到我都想偷我弟的羽戎衣來穿！為什麼公司發的宣傳衣是短袖，為什麼我明明是興高采烈的想去說明會，卻是這樣的天氣歡迎我，知道嗎？這就回到剛剛講的：門的另一端，真實的世界…&lt;/p&gt;  &lt;p&gt;儘管如此，這世間還是有不變的美好！要我舉例來說嗎？&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;嗯嗯，那就像我印象中的台南永遠都是有陽光的，高鐵只要一過曾文溪就會看到太陽。 &lt;/li&gt;    &lt;li&gt;李強老師永遠不記得我的名字，卻永遠記得我這個學生，記得我修過他什麼課、幹過什麼壞事，這次到是不忘跟我要名片！ &lt;/li&gt;    &lt;li&gt;黃宗立老師跟我打招呼的速度一定比我跟他打招呼快！ &lt;/li&gt;    &lt;li&gt;黃崇明老師一直記得我在蘇小鈺手下打雜！ &lt;/li&gt;    &lt;li&gt;每次要找朱治平老師，他永遠不在辦公室！！ &lt;/li&gt;    &lt;li&gt;永遠以為楊中平老師跟我一樣菜 -_-|| &lt;/li&gt;    &lt;li&gt;老師的女兒德恩不管看過我們幾次，每次的印象卻都像是要砍掉重練，從零開始、再出發！ &lt;/li&gt;    &lt;li&gt;老師辦公室的唱片還是很多，不時還會有陣陣木頭香！ &lt;/li&gt;    &lt;li&gt;showmin, 文森, D.N.A 永遠很捧場，buffett 一定要坐在角落，aaa 一定要遲到。 &lt;/li&gt;    &lt;li&gt;冠廷一定要提早會消失（哪怕我們有革命情感），bbb 一定要耍龜毛！ &lt;/li&gt;    &lt;li&gt;老師一定會問我：我的 P2P player 呢？我的黑膠呢？ &lt;/li&gt;    &lt;li&gt;最後，在回台北的高鐵上，計畫著下次什麼時候再來？（這樣會不會被發現我是敗家子，都坐高鐵來回 -_-） &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;回到正題，出差是為了宣傳騰雲駕霧程式競賽，雖然來的人不多，不過也讓我體驗到什麼是一字之差的 mindset：&lt;/p&gt;  &lt;p&gt;Royce：會來的就是會來！    &lt;br /&gt;Keiko：該來的就是會來！&lt;/p&gt;  &lt;p&gt;不過還是有感動的事，遇到三個電通所的學弟，雖然不知道他們是從哪看來的網宣，可能是系學會幫的忙，不過從他們堅定的眼神看得出來他們會參加！&lt;/p&gt;  &lt;p&gt;最後，也是最重要的一點，說明會前遇到了系主任，在他大力支持下， 4/17 （五）下午 2:00 開始的 seminar 我們又可以再去一次了！天啊，意義非凡，因為星期五下去，表示可以星期 X 才回台北！&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-847303806978817410?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/847303806978817410/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=847303806978817410' title='7 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/847303806978817410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/847303806978817410'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/03/blog-post_26.html' title='出差出差！'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_2ZMoTkLFVu8/ScpYn5QndmI/AAAAAAAAAf0/A-FTZLFYmMA/s72-c/wang0zc5_thumb.jpg?imgmax=800' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-51266123806499456</id><published>2009-03-22T22:07:00.001+08:00</published><updated>2009-03-22T22:07:52.031+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming Language'/><title type='text'>Domain-Specific Language (DSL)</title><content type='html'>&lt;h2&gt;前言&lt;/h2&gt;  &lt;p&gt;過去幾年蠻熱門的話題（?），原本還想來學院派式的追本溯源一下，不過凡事起頭難，手邊資料不多，很多論文又不能下載，就作罷了，當閒聊了，又不是要寫論文 XD&lt;/p&gt;  &lt;p&gt;我想是因為自己很晚才接觸資訊這個領域，加上上個世紀，網路、社群並非如此盛行，總有種錯覺：這幾年許多新語言的出現不再宣稱自己能解決所有的問題、可以被應用在所有領域，而是將焦點專注於特定問題、領域（domain）的，當然，這不是個新概念，但 Domain-specific language 卻是這幾年才流行起來的。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/ScZGMRzIkmI/AAAAAAAAAfo/UXqY_BIRpJA/s1600-h/GenerativeProgramming3.jpg"&gt;&lt;img title="Generative Programming" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="144" alt="Generative Programming" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/ScZGNrbII8I/AAAAAAAAAfs/7YvT_qR-dtk/GenerativeProgramming_thumb1.jpg?imgmax=800" width="115" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Generative Programming 一書是這麼描述 DSL 的：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;A domain-specific language (DSL) is a specialized, &lt;font color="#ff0000"&gt;problem-oriented&lt;/font&gt; language. …(略) ... Domain-specific languages can be textural (e.g. SQL) or graphical (e.g. the graphical specification of a GUI in a GUI builder).&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;哈，基本上這是個很寬鬆的描述，會被 reviewer 打槍的那種，不過不難想像到 DSL 概念的成品已經充斥著我們生活周遭，像是：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;lex &amp;amp; yacc：大學 compiler 課用會到！ &lt;/li&gt;    &lt;li&gt;SQL &lt;/li&gt;    &lt;li&gt;曾經 &lt;a href="http://slime.sourceforge.net/" target="_blank"&gt;SLIM&lt;/a&gt; 想用的 XUL ，到後來自己設計的 component script &lt;/li&gt;    &lt;li&gt;SMP 的 SREAM script &lt;/li&gt;    &lt;li&gt;ChucK （那有沒有 SCREAM 呢！） &lt;/li&gt;    &lt;li&gt;微軟 .Net 新一代的 GUI 平台用到的 XAML（很多 open source GUI framework 也有類似的概念） &lt;/li&gt;    &lt;li&gt;UML 中的 OCL &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;這幾年 VM 這種結合 compiler, interpreter 特性的平台語言很是盛行，透過重複利用 VM 的中間碼可以讓原本設計一個 programming langauge 需要的繁雜後端工作得到部份減輕。所以許多研究、實驗性質的 DSL 會考慮建構在 VM 之上。舉例來說，就有許多語言建構在 JVM 之上，參考&lt;a href="http://en.wikipedia.org/wiki/List_of_JVM_languages" target="_blank"&gt;這邊&lt;/a&gt;。&lt;/p&gt;  &lt;h2&gt;優點&lt;/h2&gt;  &lt;p&gt;那到底 DSL 的好處是什麼呢？&lt;a href="http://en.wikipedia.org/wiki/Domain-specific_programming_language" target="_blank"&gt;wiki&lt;/a&gt; 和 &lt;a href="http://homepages.cwi.nl/~arie/papers/dslbib/" target="_blank"&gt;Domain-Specific Language: An Annotated Bibliography&lt;/a&gt; 做了很好的條列和解釋，不過我還是想再說一遍：（ -_-||唉，我想我個性不太好）&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Expressive：我想這是最重要一點，人類的思考會受到語言、符號、圖像的限制。因此 DSL 在描述問題、解決問題時都會比 general purpose language （暫用 GPL 代表）更能貼近核心。最顯而易見的例子就是 GUI 的設計，用 WYSIWYG 的方式刻繪介面會比純文字好、BNF&amp;#160; form 比一堆 if, else, loop 湊出來的 FSM 更能表達語言結構、SQL 語法比用 procedural 清晰。此外，好的表達力可以讓維護程式碼時，一目了然，不需太多註解、文件相輔，一行 DSL 程式碼表達的運算可能需要數行 GPL 才能完成，這種精簡效果是很可觀的！ &lt;/li&gt;    &lt;li&gt;語法支持：這個部份我最想挑出來說的是 domain-specific error report/checking 和 constraint enforcement。好的語言不僅給予程式設計師自由的空間去發會，還要能適時給予程式設計師提醒與限制。 enforcement 是我進公司後才體驗到的一個 term ，這裡或許反映出一個個人喜好，我不喜歡把錯誤推遲到執行時期發現。不同的應用中常會帶來不同的限制或者說是規範，最糟糕的情況是無法透過 GPL 既有元素去表達的，或是僅能在執行時期偵測、或是以間接、隱晦的方式去表現。 &lt;/li&gt;    &lt;li&gt;其他，如可以做到更好的最佳化、程式碼內嵌 domain knowledge、易於測試等。（哈，我用其他來帶過，其實就代表我個人認為前兩項是最重要的好處） &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;為了避免空口說白話，這邊以 C++ 實做一個矩陣為例子來說明 GPL 可能做不好的地方：&lt;/p&gt;  &lt;pre class="brush: cpp"&gt;class MyMatrix {
public:
    MyMatrix();
    MyMatrix( int row, int col );

    int operator ()( int row, int col );
    vector&amp;lt;int&amp;gt;&amp;amp; operator []( int row );
    template &amp;lt;typename T&amp;gt;
    MyMatrix&amp;amp; operator =( const T&amp;amp; );

private:
    int     row_;
    int     col_;
    vector&amp;lt; vector&amp;lt;int&amp;gt; &amp;gt;   data_;
};&lt;/pre&gt;

&lt;p&gt;使用時很簡單，就像下面一樣，精練、不失矩陣的意含（我想是這樣沒錯）：&lt;/p&gt;

&lt;pre class="brush: cpp"&gt;    MyMatrix m1( 10, 10 );&lt;/pre&gt;

&lt;p&gt;第一步看起來不錯，但是很明顯的當我們想初始化矩陣時，無論我們怎麼努力，卻很難只靠 C++ 本身（先不討論 Preprocessor）做到像下面的效果：&lt;/p&gt;

&lt;pre class="brush: cpp"&gt;    MyMatrix m2 = { { 0, 0 }, { 0, 0 } };&lt;/pre&gt;

&lt;p&gt;最多我們只能靠著 operator overloading 做到：&lt;/p&gt;

&lt;pre class="brush: cpp"&gt;    for ( int i = 0; i &amp;lt; 10; ++i ) {
        for ( int j = 0; j &amp;lt; 10; ++j ) {
            m1[ i ][ j ] = i + j;
        }
    }&lt;/pre&gt;

&lt;p&gt;或是提供 MyMatrixRow, MyMatrixCol 之類的 Proxy class 去一次設定多個元素；但無論如何，當元素間沒有規則時，一個一個指定矩陣元素的步驟就跑不了，此時若是有個 Matrix 相關的 DSL 輔助，我們可以寫出更精練、具可讀性的程式。下一個我們會面臨的問題可能發生在矩陣運算上，以加法為例，兩個相加的矩陣必須具有同樣的維度，但這個限制（或說規範）在 MyMatrix 是無法直接表達的（請先不要考慮到 C++ template，首先是因為這不是每個語言都有的 feature，其次是之後會有個段論詳細解釋這部份），所以我們可能得在&lt;/p&gt;

&lt;pre class="brush: cpp"&gt;MyMatrix operator +( const MyMatrix&amp;amp; lhs, const MyMatrix&amp;amp; rhs );&lt;/pre&gt;

&lt;p&gt;的實做時，去檢查矩陣的維度，當兩者不符合時丟出一個 excption。當然不是說 exception 不好，而是若是能越早發現錯誤會更好，尤其是這種維度的指定與推導是可以靜態完成的，實在沒有必要留待動態時期去偵測。此時若是有個 Matrix 相關的 DSL 可以在撰寫時給予這方面的限制，可以省去不少麻煩、也能提高程式效能。&lt;/p&gt;

&lt;h2&gt;缺點&lt;/h2&gt;

&lt;p&gt;說完 DSL 的優點，聽起來是如此好用，讓我也一度著迷，想做些 DSL 出來用，不過現實世界當然不會如此美好！DSL 最大的問題在於：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;草創期 
    &lt;br /&gt;實做一個 DSL 需要許多人力投入在設計、實做上，先期的 domain/problem 分析、研究更是花費人工。這階段最惱人的應該是穩定度吧？！ &lt;/li&gt;

  &lt;li&gt;初期 
    &lt;br /&gt;當語言實做完成後，下一個面臨的問題就是配套與使用者心理。即使語言再簡單，都還是有自己的中心哲學，對於使用者來說：他們是不是快速的學習、語言的 Learning curve 是不是適當呢？甚至使用者可能排斥再學一個新語言？接著實際開發時，是不是相關的 tool chain 都能搭配上，是不是能有好用的 editor、IDE 來輔助開發、吸引開發者目光。而其中最為麻煩的，我想是錯誤資訊（像是 compiler error、failed to code gen …）與 debug 的環境，該如何讓使用者快速 trouble shooting 是很重要的。即使今天我們提供的 DSL 只是做 transformation，把 MyMatrix DSL 轉成 C++ 而已，錯誤資訊的轉換是恨重要的，有用過 lex/yacc 的人可以回憶一下，在寫錯 lex/yacc 的程式時，lex/yacc 的 codegen 程式有時不會知道，它們只能根據預先的條件去轉換成 C 語言，當送給 C compiler 時才會 compile errors，此時使用者該如何從這樣的錯誤對應回 lex/yacc 的錯誤呢？當然最好的方式是，使用者不必以 codegen 後的角度去找尋錯誤，而是直接面對他們寫的 DSL 程式去找錯（像是 lex, yacc 程式碼、MyMatrix），同樣地，debug 也是面臨同樣問題，lex/yacc 雖然在code generation 時會把對應的行號、檔名寫到產生出來的 .c 檔中，但用 C debugger 回頭看到的卻是 FSM 和 LALR 的程式，個人認為使用者是很容易迷路的！ &lt;/li&gt;

  &lt;li&gt;中期 
    &lt;br /&gt;維護，像是文件、社群資源等都是需要長時間投入的。 &lt;/li&gt;

  &lt;li&gt;長期 
    &lt;br /&gt;想必該是面對改版相容性問題時候了！ &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;DSL 的形式&lt;/h2&gt;

&lt;p&gt;從 DSL 的實做方式以及它怎麼跟其他語言合作，我們可以大致上分成下面幾種，並且從設計、實做與使用上來討論一下：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Fixed, separate DSLs 
    &lt;br /&gt;這是最常見的一種形式，DSL 擁有自行一套的 tool chain 甚至執行環境，例如 SQL 。這種形式的 DSL 最大的問題是很難跟其他語言進行良好的整合，可能是語言特性（static vs. dynamic）、執行方式（compiler vs. interpreter）、執行環境的差異、tool chain 等因素造成。即使是可以透過一定的手法把 separate DSLs 轉為 embedded DSLs，但仍不是很方便。而 DSL 實做上呢？從頭到尾打造一個 DSL 是很曠日費時，而且成本極高的一件事，更不要談說相關的開發環境。簡單的說， DSL 和他要合作的語言間太鬆綁了（loose coupling），loose coupling 有時不是件好事。 &lt;/li&gt;

  &lt;li&gt;Embedded DSLs 
    &lt;br /&gt;另一種方式是我們可以在 GPL 中定義相關的類別、函式去包裝 DSL ，讓開發過程中，DSL 與 GPL 是緊緊地包在一起的，這聽起來比 separate DSLs 好，但是根據實做出的合作方式，卻可能比 separate DSLs 好不到哪裡去，舉個例子來說，很多 database 都會有不同語言的 interface library 供開發者使用，PostgreSQL 有一個 C++ 介面的函式，叫做 libpgxx ，它與 PostgreSQL 連接的方式是： 

    &lt;br /&gt;

    &lt;pre class="brush: cpp"&gt;int playWithDb() {
    connection Conn( &amp;quot;dbname=test&amp;quot; );
    {
        work Xaction( Conn, &amp;quot;DemoTransaction&amp;quot; );
        result r = Xaction.exec( &amp;quot;DELETE FROM &amp;quot; + Table + &amp;quot; WHERE ID=&amp;quot; + ID );

        for ( result::size_type i = 0; i != R.size(); ++i ) {
            Process(R[i][&amp;quot;lastname&amp;quot;]);
        }
    }
}&lt;/pre&gt;
或是看個 C++ 與 TCL 的整合： 

    &lt;br /&gt;

    &lt;pre class="brush: cpp"&gt;void hello()
{
     cout &amp;lt;&amp;lt; &amp;quot;Hello C++/Tcl!&amp;quot; &amp;lt;&amp;lt; endl;
}

int main()
{
     interpreter i;
     i.def(&amp;quot;hello&amp;quot;, hello);

     string script = &amp;quot;for {set i 0} {$i != 4} {incr i} { hello }&amp;quot;;

     i.eval(script);
}&lt;/pre&gt;
不難發現這種倚賴參數、字串來執行 DSL 的方式讓我們失去了機會去做一些事情： 

    &lt;ol&gt;
      &lt;li&gt;express domain-specific optimization &lt;/li&gt;

      &lt;li&gt;domain-specific error report:&amp;#160; syntax error 和 debug 是我認為尤其重要的，像是 compile time 的 error/constraint enforcement ！ &lt;/li&gt;

      &lt;li&gt;domain-specific syntax &lt;/li&gt;
    &lt;/ol&gt;
不過幸運的是，有另外一種方式可以讓我們從 GPL 中衍生 DSL ，那就是 metaprogramming ，雖然不是每種語言都有這種特性，也不是擁有這種特性後就能一切完美。以 C++ 來說，我們可以透過 template metaprogramming 做到 code generation 和 code optimization ，甚至透過 C++ 型別去做部份的 error report/checking。但大部分時候仍是補強而已，很多 domain-specific 的事還是得推延到 run time。這邊想示範一個簡單的 C++ metaprogramming 利用型別實做 constraint enforcement 的概念，那就再次請出 Matrix 來當例子，這次我想針對維度做出 constraint enforcement ，那我們可以把原本的實做改成像下面這樣： 

    &lt;br /&gt;

    &lt;pre class="brush: cpp"&gt;template &amp;lt;int RowT, int ColT&amp;gt;
class MyMatrix {
public:
    friend MyMatrix operator +( const MyMatrix&amp;amp; lhs, const MyMatrix&amp;amp; rhs );

    MyMatrix();

    int operator ()( int row, int col );
    vector&amp;lt;int&amp;gt;&amp;amp; operator []( int row );
    template &amp;lt;typename T&amp;gt;
    MyMatrix&amp;amp; operator =( const T&amp;amp; );

    static const int RowDimension = RowT;
    static const int ColDimension = ColT;

private:
    vector&amp;lt; vector&amp;lt;int&amp;gt; &amp;gt;   data_;
};&lt;/pre&gt;
注意到沒有，我們把維度的概念帶入型別之中，那麼下面的程式碼，&amp;#160; &lt;br /&gt;&amp;#160; &lt;pre class="brush: cpp"&gt;    MyMatrix&amp;lt;10, 10&amp;gt; m1;
    MyMatrix&amp;lt;2, 2&amp;gt;   m2;

    cout &amp;lt;&amp;lt; m1 + m2 &amp;lt;&amp;lt; endl;&lt;/pre&gt;
便可以在 compile time 丟出錯誤，下面是 VC 2005 的錯誤訊息： 

    &lt;blockquote&gt;
      &lt;p&gt;error C2679: binary '+' : no operator found which takes a right-hand operand of type 'MyMatrix&lt;rowt  ,COLT&gt;' (or there is no acceptable conversion)&lt;/p&gt;
    &lt;/blockquote&gt;
但是細心的你注意到了嗎？即使我們把錯誤拉前了，但這樣的錯誤訊息並不是跟矩陣有太大關係，如果能丟出 

    &lt;br /&gt;

    &lt;blockquote&gt;
      &lt;p&gt;incompatible dimensions&lt;/p&gt;
    &lt;/blockquote&gt;
是不是更好呢？在 GPL 中，我們有時是很難做到完整的 domain-specific error report/checking 的 。再者，並不是每種 constraint 都適合以型別的方式表達，一來可能造成 template parameter 數量爆增，這可能增加 compile 時間，二來也暴露太多細節在 client code 中，這會讓程式碼難以擴充維護。 

    &lt;br /&gt;雖然用了 C++ template 當例子，不過值得提一下， template haskell 似乎也很有趣，許多 functional language 都可以一些語言擴充！ &lt;/li&gt;

  &lt;li&gt;Modularly composable DSLs 
    &lt;br /&gt;腦子很小的我，只想出前面兩種，這第三種形式是 Generative Programming 一書提出的，它強調的是在語言的基礎建設（infrastructure）完善皆備的情況下，去開發語言的 plug-in ，說來神奇，其實不會， C/C++ 的 preprocessor 或是更古老的 Smalltalk 和 CLOS 都是這種概念的雛型。只是它們未能在 domain-specific 的需求上達到更好的精細度。或許看到這裡，你會有跟我一樣的一個疑問：那 Modularly composable DSLs 與 Embedded DSLs 有什麼不同呢？聽起來都是建構在既有語言之上，其實這中間有個隱微的差異，可以細細體驗一下： 

    &lt;br /&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Embedded DSLs 的根基是現有語言的 syntax，而 Modularly composable DSLs 則是做 syntax extensions。&lt;/p&gt;
    &lt;/blockquote&gt;
這句話代表的是，Embedded DSLs 的使用是類似於使用 GPL 的 library 或是 framework 的，其 syntax/semantic 跟原本 GPL 是一樣的。但 Modularly composable DSLs 是構造在 GPL infrastructure 之上，除了既有的 syntax/semantic 外，我們還可以增加 domain-specific 的 syntax/semantic ，甚至是刪去、捨棄既有的。若是想更細部條列兩者的差異，或許可以參考 Generative Programming 所條列的，Modularly composable DSLs 可以比 Embedded DSLs 做到： 

    &lt;ol&gt;
      &lt;li&gt;Syntax extensions &lt;/li&gt;

      &lt;li&gt;Semantic extensions or modifications of language constructs &lt;/li&gt;

      &lt;li&gt;Domain-specific optimizations &lt;/li&gt;

      &lt;li&gt;Domain-specific type systems &lt;/li&gt;

      &lt;li&gt;Domain-specific error checking and reporting &lt;/li&gt;
    &lt;/ol&gt;
再回到 language infrastructure 上， 我們有什麼辦法可以操作 language infrastructure 呢？有幾種可能性： 

    &lt;ol&gt;
      &lt;li&gt;Preprocessor &lt;/li&gt;

      &lt;li&gt;Metaprogramming &lt;/li&gt;

      &lt;li&gt;Modularly Extendible Compilers and Modularly Extendible Programming Environments &lt;/li&gt;
    &lt;/ol&gt;
前兩者在許多語言上已經可以做到，正如前面提到的 C/C++, Smalltalk, Haskell 和 CLOS 都行，只是做的不夠好。因為這不只是語言本身支援的問題，還牽扯到 tool chain 與環境。至於第三種，則可以參考 &lt;a href="http://en.wikipedia.org/wiki/Charles_Simonyi" target="_blank"&gt;Charles Simonyi&lt;/a&gt; （是的，就是微軟的那位大師，匈牙利命名法、WYSIWYG document 發明者、 Word 之父）的研究 – &lt;a href="http://research.microsoft.com/apps/pubs/default.aspx?id=69540" target="_blank"&gt;Intentional Programming&lt;/a&gt; 。大師在 &lt;a href="http://research.microsoft.com/apps/pubs/default.aspx?id=69540" target="_blank"&gt;Microsoft Research&lt;/a&gt; 以及後來開設的 &lt;a href="http://www.intentsoft.com/" target="_blank"&gt;Intentional Software&lt;/a&gt; 公司都可以找到這方面的發表與研究成果，研究開始得很早，約莫在上個世紀的 90 年代初，未來有時間，希望能玩玩看再來跟大家分享一下！&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;結語&lt;/h2&gt;

&lt;p&gt;這篇文章真是超長，內容又很空洞，可是我打了兩天，大概是我在低潮吧…不過還是想跟大家分享一下幾點：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Compiler is your friend! &lt;/li&gt;

  &lt;li&gt;Constraint enforcement is your friend!&lt;/li&gt;

  &lt;li&gt;Compile-time error report/checking is your friend!&lt;/li&gt;

  &lt;li&gt;The last but most important point, C++ is your friend!&lt;/li&gt;
&lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-51266123806499456?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/51266123806499456/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=51266123806499456' title='10 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/51266123806499456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/51266123806499456'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/03/domain-specific-language-dsl.html' title='Domain-Specific Language (DSL)'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_2ZMoTkLFVu8/ScZGNrbII8I/AAAAAAAAAfs/7YvT_qR-dtk/s72-c/GenerativeProgramming_thumb1.jpg?imgmax=800' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-8798267803840818908</id><published>2009-03-19T22:26:00.001+08:00</published><updated>2009-03-19T22:50:21.167+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Book'/><title type='text'>歐萊禮書籍特價，三本以上 75 折</title><content type='html'>&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/ScJWCz0m4bI/AAAAAAAAAfg/peY7RuvBe_Y/s1600-h/image%5B7%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; border-left: 0px; margin-right: auto; border-bottom: 0px" height="227" alt="image" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/ScJWEWSNaxI/AAAAAAAAAfk/JUUUzTDQKiE/image_thumb%5B5%5D.png?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;學弟的版看到了，趕快來廣告一下，雖然都是中文書，不過掛著 O’Reilly 至少不會太差唷，是不是要開團了！&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.books.com.tw/exep/activity/activity.php?id=0000017976&amp;amp;sid=0000017976&amp;amp;page=291" href="http://www.books.com.tw/exep/activity/activity.php?id=0000017976&amp;amp;sid=0000017976&amp;amp;page=291"&gt;http://www.books.com.tw/exep/activity/activity.php?id=0000017976&amp;amp;sid=0000017976&amp;amp;page=291&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;目前看上了：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;深入淺出物件導向分析與設計&lt;/li&gt;    &lt;li&gt;Linux 核心詳解&lt;/li&gt;    &lt;li&gt;Linux 驅動程式（這有&lt;a href="http://lwn.net/Kernel/LDD3/" target="_blank"&gt;電子版&lt;/a&gt;）&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;聽說還不錯的：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;讓事情發生--專案管理之美學，第二版&lt;/li&gt;    &lt;li&gt;軟體預先架構之美學&lt;/li&gt;    &lt;li&gt;程式設計師提升生產力秘笈&lt;/li&gt;    &lt;li&gt;操作介面設計模式&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;推薦的：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;UML 2.0學習手冊     &lt;br /&gt;不知道有沒有特別有名，沒有特別針對哪種軟體工程方法論做介紹，單純講 UML diagrams ，感覺很清爽易讀！&lt;/li&gt;    &lt;li&gt;深入淺出－設計模式     &lt;br /&gt;很經典的書，不過看久了覺得很囉唆，唉，我真是難伺候！&lt;/li&gt;    &lt;li&gt;深入資料庫之美學     &lt;br /&gt;有點深，害我都放在書架上！&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;入門的、可當工具書的：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;建構嵌入式Linux系統&lt;/li&gt;    &lt;li&gt;Python 學習手冊&lt;/li&gt;    &lt;li&gt;精通CVS&lt;/li&gt;    &lt;li&gt;防駭超級工具&lt;/li&gt;    &lt;li&gt;防駭戰士&lt;/li&gt;    &lt;li&gt;GNU Make 專案開發工具&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;觀望中：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;美麗程式：頂尖程式設計師的思考方式     &lt;br /&gt;在成大圖書部翻過，覺得都是淺嘗則止的帶過一些東西。&lt;/li&gt;    &lt;li&gt;Linux 系統程式設計     &lt;br /&gt;看了目錄，感覺有更好的選擇！&lt;/li&gt;    &lt;li&gt;輕快的好 Java     &lt;br /&gt;在成大圖書部翻過，不過內容已經忘了，沒有什麼印象，但好像有提過一些觀念 -_-||&lt;/li&gt;    &lt;li&gt;Java I/O 技術     &lt;br /&gt;有點舊！&lt;/li&gt;    &lt;li&gt;超越Java：探討程式語言的未來     &lt;br /&gt;蠻有趣的書，不過論點似乎有點 ooxx ，是本可以戰起來的書！&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;考慮去書店翻翻的或是有人要借我翻閱嗎？&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Java 效能調校技巧&lt;/li&gt;    &lt;li&gt;Java Data Object 深度探討&lt;/li&gt;    &lt;li&gt;Java 虛擬機器&lt;/li&gt;    &lt;li&gt;Java Threads&lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-8798267803840818908?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/8798267803840818908/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=8798267803840818908' title='3 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/8798267803840818908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/8798267803840818908'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/03/75.html' title='歐萊禮書籍特價，三本以上 75 折'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_2ZMoTkLFVu8/ScJWEWSNaxI/AAAAAAAAAfk/JUUUzTDQKiE/s72-c/image_thumb%5B5%5D.png?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-152984345498620974</id><published>2009-03-18T22:15:00.001+08:00</published><updated>2009-03-18T22:15:18.630+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Blog'/><title type='text'>在 blog 上貼 YouTube</title><content type='html'>&lt;p&gt;&lt;a href="http://ludwig-arwen.blogspot.com/" target="_blank"&gt;網友 Alvin&lt;/a&gt; 最近詢問怎麼在 blog 上嵌入 YouTube 一類的元件，所以就來跟大家介紹一下，順便騙騙文章數，掩飾一下自己江郎才盡了…&lt;/p&gt;  &lt;h3&gt;步驟一&lt;/h3&gt;  &lt;p&gt;YouTube 之類的服務都有提供物件語法給大家複製到自己的網頁上，參考下圖可以看到網頁有一區標示著&lt;font color="#ff0000"&gt;嵌入&lt;/font&gt;。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/ScD-P-LwuxI/AAAAAAAAAfA/iUL5_tG20Jg/s1600-h/ScreenHunter_01%20Mar.%2018%2021.28%5B6%5D.jpg"&gt;&lt;img title="ScreenHunter_01 Mar. 18 21.28" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="185" alt="ScreenHunter_01 Mar. 18 21.28" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/ScD-Q82RpVI/AAAAAAAAAfE/JriYWqZVxYk/ScreenHunter_01%20Mar.%2018%2021.28_thumb%5B4%5D.jpg?imgmax=800" width="416" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;步驟二&lt;/h3&gt;  &lt;p&gt;滑鼠移過去，還會發現有自訂的功能。使用者可以根據自己的需求調整，調整後，就是把 &amp;lt;object&amp;gt; …開頭的語法複製起來。&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="363" alt="image" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/ScD-SvbTK-I/AAAAAAAAAec/aDKlCCsfQys/image_thumb%5B2%5D.png?imgmax=800" width="315" border="0" /&gt;&lt;/p&gt;  &lt;h3&gt;步驟三&lt;/h3&gt;  &lt;p&gt;開啟自己 blog 文章編輯的 html 模式，以 WLW 為例，就是切換到&lt;font color="#ff0000"&gt;程式碼模式&lt;/font&gt;。 接著就勇敢的貼上吧！&lt;/p&gt;  &lt;h3&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/ScD-T9oTIMI/AAAAAAAAAfQ/3tfDapzYPjQ/s1600-h/ScreenHunter_04%20Mar.%2018%2021.55%5B5%5D.jpg"&gt;&lt;img title="ScreenHunter_04 Mar. 18 21.55" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="236" alt="ScreenHunter_04 Mar. 18 21.55" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/ScD-VrbidgI/AAAAAAAAAfY/ufqa6aKq01U/ScreenHunter_04%20Mar.%2018%2021.55_thumb%5B3%5D.jpg?imgmax=800" width="374" border="0" /&gt;&lt;/a&gt;&lt;/h3&gt;  &lt;h3&gt;成果&lt;/h3&gt;  &lt;p&gt;最後，就可以看到成果了！&lt;/p&gt;  &lt;p align="center"&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/XjM1Lrsb7I8&amp;amp;hl=zh_TW&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/XjM1Lrsb7I8&amp;amp;hl=zh_TW&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h3&gt;其他&lt;/h3&gt;  &lt;p&gt;其他像是 mp3, quicktime 等格式的多媒體資料，基本上只要 host 有提供 object 來嵌入，都可以在網頁上產生美美的元件。&lt;/p&gt;  &lt;h3&gt;結語&lt;/h3&gt;  &lt;p&gt;ㄜ，感覺教學最後就要來個結語，那就： Yes, We Can! &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-152984345498620974?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/152984345498620974/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=152984345498620974' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/152984345498620974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/152984345498620974'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/03/blog-youtube_18.html' title='在 blog 上貼 YouTube'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_2ZMoTkLFVu8/ScD-Q82RpVI/AAAAAAAAAfE/JriYWqZVxYk/s72-c/ScreenHunter_01%20Mar.%2018%2021.28_thumb%5B4%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-5816880289482686376</id><published>2009-03-06T00:21:00.001+08:00</published><updated>2009-03-06T00:22:37.085+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>長尾效應（The Long Tail）</title><content type='html'>&lt;p&gt;為了為裝成統計達人，&lt;a href="http://keikoblog.blogspot.com/2009/03/blog-post.html" target="_blank"&gt;上上一篇文章&lt;/a&gt;用了長尾效應，不過馬上就被 &lt;a href="http://fruitfoxlu.blogspot.com/" target="_blank"&gt;Royce 大&lt;/a&gt;戳破，解釋得零零落落，還好 Wesley 馬上挺身救愛徒&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/Sa_8B-FuTYI/AAAAAAAAAdw/rK6qVUI2npI/s1600-h/6TRYWO4km%2B12DJLfVSRV2OcUpK4%3D%5B2%5D.gif"&gt;&lt;img title="6TRYWO4km 12DJLfVSRV2OcUpK4=" style="display: inline" height="50" alt="6TRYWO4km 12DJLfVSRV2OcUpK4=" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/Sa_8C9M2xqI/AAAAAAAAAd0/XyqZfh712gI/6TRYWO4km%2B12DJLfVSRV2OcUpK4%3D_thumb.gif?imgmax=800" width="50" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;不過還是來解釋一下什麼是長尾效應，我想最常聽到的例子就是 Amazon 吧？！有人研究了 Amazon 賣的書和銷售排名關係後，發現銷售排名低的書即使不熱門但為數眾多，累積起來的銷售額還大於熱門書籍！&lt;/p&gt;  &lt;p&gt;或是更簡單、更流行的說法就是：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/Sa_8ELb9R5I/AAAAAAAAAd4/Ll4bbeBc1CA/s1600-h/BeatTen%5B3%5D.jpg"&gt;&lt;img title="BeatTen" style="border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; border-left: 0px; margin-right: auto; border-bottom: 0px" height="276" alt="BeatTen" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/Sa_8FKXGg9I/AAAAAAAAAd8/lC8MsDfy3PY/BeatTen_thumb%5B1%5D.jpg?imgmax=800" width="484" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;舉個例子來說：&lt;/p&gt;  &lt;p&gt;Keiko 只有 Royce 萬分之一的戰鬥力！可是我有千千萬萬個 Keiko ，然後 Keiko&lt;font color="#ff0000"&gt;s&lt;/font&gt; 就打贏了 Royce…&lt;/p&gt;  &lt;p&gt;不是小兵立大功，是小兵們立大功！所以注意到沒，Keiko 要用複數型！&lt;/p&gt;  &lt;p&gt;接著就開始很多人用這個詞了，像我這種常上網的阿宅，每天在一堆的 Web 2.0 應用或是趨勢研究中都會看到它，有時候看到的次數比我當天寫出來的 bug 還多…&lt;/p&gt;  &lt;hr /&gt;  &lt;p&gt;唉，不過我是那種很難相處又反社會的人，這種詞看多了就會有股莫名的火燒上心頭！然後我就開始幻想一種對話：&lt;/p&gt;  &lt;p&gt;猩仙人：前輩，為什麼你都這麼早開始對程式最佳化？   &lt;br /&gt;偽前輩 Keiko：你不知道嗎？80-20 落伍了，長尾正夯！在 80% 的 code 做最佳化搞不好會比你在 20% 的程式做最佳化來的有用唷！    &lt;br /&gt;猩仙人：又學到一招了，前輩，我好崇拜你唷！（筆記、筆記）    &lt;br /&gt;Royce：&amp;lt;囧&amp;gt;    &lt;br /&gt;mobo：Keiko 毀人不倦！&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-5816880289482686376?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/5816880289482686376/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=5816880289482686376' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5816880289482686376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5816880289482686376'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/03/long-tail.html' title='長尾效應（The Long Tail）'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_2ZMoTkLFVu8/Sa_8C9M2xqI/AAAAAAAAAd0/XyqZfh712gI/s72-c/6TRYWO4km%2B12DJLfVSRV2OcUpK4%3D_thumb.gif?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-8630278369585155586</id><published>2009-03-04T23:35:00.001+08:00</published><updated>2009-03-04T23:35:30.090+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>心存歹念，會有報應！</title><content type='html'>&lt;p&gt;今天幫友 team 的客戶跑 beta 程式，馬上就遇到一個問題，我不是那種很會找 bug 的人，事實上也還在等對方驗證是不是 bug ，可我腦海中就想到一句話：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;當你看到一隻蟑螂，表示還有一百隻；      &lt;br /&gt;當你看到一隻bug，表示…&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;然後，回家報應就來了…&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/Sa6fuuVnneI/AAAAAAAAAdo/Sx5_lwnNtIo/s1600-h/DSC05499%5B5%5D.jpg"&gt;&lt;img title="DSC05499" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="364" alt="DSC05499" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/Sa6fwInqBnI/AAAAAAAAAds/OdceM8jccCw/DSC05499_thumb%5B3%5D.jpg?imgmax=800" width="484" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;hr /&gt;  &lt;p align="center"&gt;有 dump 耶，我應該看嗎？&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-8630278369585155586?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/8630278369585155586/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=8630278369585155586' title='3 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/8630278369585155586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/8630278369585155586'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/03/blog-post_04.html' title='心存歹念，會有報應！'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_2ZMoTkLFVu8/Sa6fwInqBnI/AAAAAAAAAds/OdceM8jccCw/s72-c/DSC05499_thumb%5B3%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-2590022792905915458</id><published>2009-03-04T00:20:00.001+08:00</published><updated>2009-03-04T00:22:49.330+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Blog'/><title type='text'>螢幕解析度統計</title><content type='html'>&lt;p&gt;最近換了新版型，發現文章區的版面大小竟然跟油價一樣是浮動的，讓我在小黑的 1024 x 768 螢幕上看到很多圖都被截掉了，這就表示很多看我 blog 的人（其實沒有很多人看，科科…）都會有同樣的狀況，原本還想發個文問問大家的意見，沒想到 &lt;a href="www.google.com/analytics" target="_blank"&gt;google analytics&lt;/a&gt; 竟然幫我統計好了！&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/Sa1YnVL0txI/AAAAAAAAAc8/xqsVHzlg_JI/s1600-h/ScreenHunter_02%20Mar.%2003%2023.26%5B4%5D.jpg"&gt;&lt;img title="ScreenHunter_02 Mar. 03 23.26" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="484" alt="ScreenHunter_02 Mar. 03 23.26" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/Sa1Yotvu2cI/AAAAAAAAAdE/J-QHXoCAHHY/ScreenHunter_02%20Mar.%2003%2023.26_thumb%5B2%5D.jpg?imgmax=800" width="434" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;然後又很無聊的看了一下，原來我的 blog ：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;“CreateProcess” 最熱門啊！那李組長眉頭一皺，揪竟，地球一天會產生多少 process 呢？ &lt;/li&gt;    &lt;li&gt;“我要變胖”用 google 去 search 排名還是 8，看來 google 不太準唷 –_-|| &lt;/li&gt;    &lt;li&gt;“黑暗之路”，這真是什麼鬼，我的文章好像沒出現過這段字，難道是黑暗騎士被斷詞找到了？ &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/Sa1YqC-RdoI/AAAAAAAAAdI/001-0O7Mpaw/s1600-h/image%5B4%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="484" alt="image" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/Sa1YrxKXkII/AAAAAAAAAdM/exDk91DWAe4/image_thumb%5B2%5D.png?imgmax=800" width="363" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;科科，接下來就是拜 ubuntu 和 mysql 兩套 open source 之賜了，對了，還要感謝 Alvin 老師讓我管實驗室主機、mobo 決定用 ubuntu + mysql！果然痛過就是要留下痕跡，這樣人家才不會再痛一次 &amp;gt;_&amp;lt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/Sa1Ysv705xI/AAAAAAAAAdQ/kE620N0Xf4c/s1600-h/image%5B10%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="128" alt="image" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/Sa1Yt2StlaI/AAAAAAAAAdU/qbMyOjOXstw/image_thumb%5B6%5D.png?imgmax=800" width="484" border="0" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;最後感謝各位的流量貢獻，我的 blog 流量四分之一來自你們的網站！（從我退伍開始 10/13 ~）&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://ludwig-arwen.blogspot.com/" target="_blank"&gt;老師&lt;/a&gt;、&lt;a href="http://87showmin.blogspot.com/" target="_blank"&gt;小明&lt;/a&gt;、&lt;a href="http://fruitfoxlu.blogspot.com/" target="_blank"&gt;小路學長&lt;/a&gt;，嗯嗯，沒有長尾效應！ &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/Sa1Yv1vfu4I/AAAAAAAAAdY/1vRmP2NCmN4/s1600-h/image%5B16%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="314" alt="image" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/Sa1YxrFycmI/AAAAAAAAAdc/UPnW5V2GaBM/image_thumb%5B10%5D.png?imgmax=800" width="484" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;天啊，&lt;a href="http://fruitfoxlu.blogspot.com/" target="_blank"&gt;小路學長&lt;/a&gt;後勢看漲唷！（最近一個月）&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/Sa1YzC7Ou8I/AAAAAAAAAdg/kqxKuqYJSIA/s1600-h/image%5B21%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="310" alt="image" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/Sa1Y07Mah5I/AAAAAAAAAdk/HJfisZLRrSo/image_thumb%5B13%5D.png?imgmax=800" width="484" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;hr /&gt;  &lt;p align="center"&gt;&lt;a href="http://kane-tomelf.blogspot.com/" target="_blank"&gt;Kane 哥&lt;/a&gt;，加油，好嗎？&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-2590022792905915458?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/2590022792905915458/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=2590022792905915458' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/2590022792905915458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/2590022792905915458'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/03/blog-post.html' title='螢幕解析度統計'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_2ZMoTkLFVu8/Sa1Yotvu2cI/AAAAAAAAAdE/J-QHXoCAHHY/s72-c/ScreenHunter_02%20Mar.%2003%2023.26_thumb%5B2%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-5791499422981394749</id><published>2009-03-01T13:02:00.001+08:00</published><updated>2009-03-01T22:29:38.250+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Debugging'/><title type='text'>Windows Debugging – Kernel Debugging with WinDbg and VMWare</title><content type='html'>&lt;p&gt;看到 &lt;a href="http://fruitfoxlu.blogspot.com/" target="_blank"&gt;Royce 大師&lt;/a&gt;開始把 &lt;a href="http://www.osronline.com/section.cfm?section=17" target="_blank"&gt;Nt Insider&lt;/a&gt; 的精華實用文章分享給大家，讓向來只有三分鐘熱度的我，也想硬著頭皮寫點東西，不過我是初學者，就從最最入門的、簡單的開始寫起吧，啊啊，希望不要變成&lt;a href="http://uncyclopedia.tw/wiki/%E5%AF%8C%E5%A5%B8%E7%97%85%E6%AF%92" target="_blank"&gt;富奸&lt;/a&gt;！&lt;/p&gt;  &lt;h3&gt;前言&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/SaoWcdlcFJI/AAAAAAAAAbk/XgXZrQjU4GU/s1600-h/mini_wininternals%5B2%5D.gif"&gt;&lt;img title="mini_wininternals" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="143" alt="mini_wininternals" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/SaoWddo1IiI/AAAAAAAAAbo/g_7kkWWPVqs/mini_wininternals_thumb.gif?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.microsoft.com/learning/en/us/Books/6710.aspx" target="_blank"&gt;Windows Internals&lt;/a&gt; 這本書是許多人進入 Windows 的第一本完整教科書，目前出到第四版，不過我一直懷疑大師 Mark E. Russinovich &amp;amp; David A. Solomon 被富奸上身，因為第五版已經推延了好幾次，目前看來會在 2009/05/20 上市，這次希望是真的。&lt;/p&gt;  &lt;p&gt;Windows Internals 第一章介紹了許多工具包來幫助我們瞭解 Windows Kernel ，其中 &lt;a href="http://www.microsoft.com/whdc/DevTools/Debugging/default.mspx" target="_blank"&gt;Debugging Tools for Windows&lt;/a&gt; 中的 WinDbg 尤其重要。透過它，我們可以去逐行執行、trace 、反組譯 Windows Kernel。&lt;/p&gt;  &lt;p&gt;Debug Windows Kernel 可以是 live （debug 自己）或是 remote （需要兩台 Windows），不過還是 remote debugging 提供了比較多的功能和彈性，傳統上，remote debugging 需要兩台電腦透過&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;null-modem cable: 也就是 serial port ，一般電腦的 COM port。 &lt;/li&gt;    &lt;li&gt;1394 &lt;/li&gt;    &lt;li&gt;USB 2.0 &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;啊，不管怎麼看兩台電腦總是很麻煩，不過幸好現在有 VMware 可以用了。把 VMware 上跑的 guest OS 當作 debugging target，在上面開啟它的 debugging port ，而提供 VMware 的 host os 則執行 WinDbg 。&lt;/p&gt;  &lt;h3&gt;VMware 設定&lt;/h3&gt;  &lt;ol&gt;   &lt;li&gt;安裝完後，開啟 guest OS 的設定。&amp;#160; &lt;br /&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/SaoWe9sYXrI/AAAAAAAAAbs/lai3KrSlpMM/s1600-h/ScreenHunter_02%20Mar.%2001%2012.24%5B5%5D.jpg"&gt;&lt;img title="ScreenHunter_02 Mar. 01 12.24" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="484" alt="ScreenHunter_02 Mar. 01 12.24" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/SaoWgsSArOI/AAAAAAAAAbw/5TNwwIhrJ0s/ScreenHunter_02%20Mar.%2001%2012.24_thumb%5B3%5D.jpg?imgmax=800" width="606" border="0" /&gt;&lt;/a&gt;       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;新增一個 Serial Port 的硬體裝置。&amp;#160; &lt;br /&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/SaoWiNUGQlI/AAAAAAAAAb0/Mk40RI1FZ0Y/s1600-h/ScreenHunter_03%20Mar.%2001%2012.26%5B4%5D.jpg"&gt;&lt;img title="ScreenHunter_03 Mar. 01 12.26" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="484" alt="ScreenHunter_03 Mar. 01 12.26" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/SaoWjgy2UbI/AAAAAAAAAb4/Ckuw1Gd8o1E/ScreenHunter_03%20Mar.%2001%2012.26_thumb%5B2%5D.jpg?imgmax=800" width="553" border="0" /&gt;&lt;/a&gt;&amp;#160; &lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/SaoWknhNUGI/AAAAAAAAAb8/aZ8GC60kiz0/s1600-h/ScreenHunter_04%20Mar.%2001%2012.27%5B4%5D.jpg"&gt;&lt;img title="ScreenHunter_04 Mar. 01 12.27" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="484" alt="ScreenHunter_04 Mar. 01 12.27" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/SaoWmGSdhWI/AAAAAAAAAcA/A33nH8esW0E/ScreenHunter_04%20Mar.%2001%2012.27_thumb%5B2%5D.jpg?imgmax=800" width="485" border="0" /&gt;&lt;/a&gt;       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;使用 Named Pipe 去模擬 Serial Port 裝置。      &lt;br /&gt;&amp;#160;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/SaoWnPXbEaI/AAAAAAAAAcE/KXKNKGAlLB8/s1600-h/ScreenHunter_05%20Mar.%2001%2012.29%5B4%5D.jpg"&gt;&lt;img title="ScreenHunter_05 Mar. 01 12.29" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="484" alt="ScreenHunter_05 Mar. 01 12.29" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/SaoWoiglgzI/AAAAAAAAAcI/Edr5zRYBZug/ScreenHunter_05%20Mar.%2001%2012.29_thumb%5B2%5D.jpg?imgmax=800" width="485" border="0" /&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;替這個 Pipe 命名，這個名字稍後會被 WinDbg 用來作為連線的名稱。        &lt;br /&gt;&amp;#160;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/SaoWpgREiXI/AAAAAAAAAcM/wjY52LjNQps/s1600-h/ScreenHunter_06%20Mar.%2001%2012.31%5B4%5D.jpg"&gt;&lt;img title="ScreenHunter_06 Mar. 01 12.31" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="484" alt="ScreenHunter_06 Mar. 01 12.31" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/SaoWrCfjZGI/AAAAAAAAAcQ/9S2fmaiM1dg/ScreenHunter_06%20Mar.%2001%2012.31_thumb%5B2%5D.jpg?imgmax=800" width="485" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;最後別忘了把 Yield CPU on Poll 選項勾起。        &lt;br /&gt;&amp;#160;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/SaoWshhsxrI/AAAAAAAAAcU/l89nJKRB-ug/s1600-h/ScreenHunter_07%20Mar.%2001%2012.33%5B4%5D.jpg"&gt;&lt;img title="ScreenHunter_07 Mar. 01 12.33" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="484" alt="ScreenHunter_07 Mar. 01 12.33" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/SaoWuBbDs-I/AAAAAAAAAcY/3uGkZisw5Gk/ScreenHunter_07%20Mar.%2001%2012.33_thumb%5B2%5D.jpg?imgmax=800" width="553" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;h3&gt;Windows Boot 設定&lt;/h3&gt;  &lt;p&gt;設定完 VMware 後，接著要設定 debugging target 也就是 guest OS 的開機選項。也就是 boot.ini 檔。修改前請先備份一下！boot.ini 是系統的隱藏檔，要看到它，要到資料夾選項中把下面兩個選項關掉：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;隱藏保護的作業系統檔案 &lt;/li&gt;    &lt;li&gt;顯示所有檔案和資料夾&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;font color="#ff0000"&gt;&lt;a href="http://fruitfoxlu.blogspot.com/" target="_blank"&gt;路大師&lt;/a&gt;補充：boot.ini 有可能是唯讀檔，若遇到不能修改的情況，請記得把唯讀的屬性拿掉！&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/SaoWvVamKnI/AAAAAAAAAcc/drCc8jeeSuM/s1600-h/ScreenHunter_08%20Mar.%2001%2012.39%5B4%5D.jpg"&gt;&lt;img title="ScreenHunter_08 Mar. 01 12.39" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="411" alt="ScreenHunter_08 Mar. 01 12.39" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/SaoWw2WSsbI/AAAAAAAAAcg/YGn5P-vp9U4/ScreenHunter_08%20Mar.%2001%2012.39_thumb%5B2%5D.jpg?imgmax=800" width="364" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;看到 boot.ini 後，在 operating systems 的選項多加一個：&lt;/p&gt;  &lt;div align="center"&gt;   &lt;pre&gt;multi(0)disk(0)rdisk(0)partition(1)\WINDOWS=&amp;quot;Microsoft Windows XP Professional - Debug&amp;quot; /fastdetect &lt;b&gt;&lt;font color="#ff0000"&gt;/debugport=com1&lt;/font&gt; &lt;font color="#0000ff"&gt;/baudrate=115200&lt;/font&gt;&lt;/b&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;要注意的是：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;debugport 的名字要跟你在設定 VMware Serial Port 時給的名字一樣才行。 &lt;/li&gt;

  &lt;li&gt;baudrate 可以任意調整成你想要的速度。 &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/SaoWyaYowAI/AAAAAAAAAck/auDr0QJLnaw/s1600-h/ScreenHunter_10%20Mar.%2001%2012.45%5B8%5D.jpg"&gt;&lt;img title="ScreenHunter_10 Mar. 01 12.45" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="137" alt="ScreenHunter_10 Mar. 01 12.45" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/SaoWzQ1uobI/AAAAAAAAAco/i7JuvlTOjPo/ScreenHunter_10%20Mar.%2001%2012.45_thumb%5B6%5D.jpg?imgmax=800" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;重開機讓 boot.ini 生效。這時會發現開機多了一個選項（如下圖），這就表示成功了。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/SaoW1NB3BbI/AAAAAAAAAcs/PnwYgRhcuc4/s1600-h/image%5B40%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="350" alt="image" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/SaoW2o-OZHI/AAAAAAAAAcw/-GBFcJeiXNU/image_thumb%5B24%5D.png?imgmax=800" width="484" border="0" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;

&lt;h3&gt;使用&lt;/h3&gt;

&lt;p&gt;最後，在使用 WinDbg 時，可以在 cmd 下這個指令：&lt;/p&gt;

&lt;pre&gt;windbg -b -k com:pipe,port=\\.\pipe\com_1,resets=0&lt;/pre&gt;

&lt;p&gt;這樣 WinDbg 就會嘗試連透過 com_1 這個 debugport 去連上 debugging target 。成功的話，應該會看到像下面的圖：&lt;/p&gt;

&lt;h3&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="484" alt="image" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/SaoW6kznowI/AAAAAAAAAc4/ZDZXu5Ry3p4/image_thumb%5B30%5D.png?imgmax=800" width="587" border="0" /&gt;&lt;/h3&gt;

&lt;h3&gt;&amp;#160;&lt;/h3&gt;

&lt;h3&gt;參考資料 &lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href="http://www.microsoft.com/whdc/DevTools/Debugging/default.mspx" target="_blank"&gt;Debugging Tools for Windows&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://silverstr.ufies.org/lotr0/windbg-vmware.html" target="_blank"&gt;Driver Debugging with WinDbg and VMWare&lt;/a&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;更新&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;2009/03/01 13：02 原文&lt;/li&gt;

  &lt;li&gt;2009/03/01 22：28 加上&lt;a href="http://fruitfoxlu.blogspot.com/" target="_blank"&gt;小路學長&lt;/a&gt;補充的 boot.ini 檔唯讀的設定。&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;p align="center"&gt;&lt;font face="Lucida Handwriting" color="#ff0000" size="5"&gt;Keep hacking, and enjoy it!&lt;/font&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-5791499422981394749?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/5791499422981394749/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=5791499422981394749' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5791499422981394749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5791499422981394749'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/03/windows-debugging-kernel-debugging-with.html' title='Windows Debugging – Kernel Debugging with WinDbg and VMWare'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_2ZMoTkLFVu8/SaoWddo1IiI/AAAAAAAAAbo/g_7kkWWPVqs/s72-c/mini_wininternals_thumb.gif?imgmax=800' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-4307254228000037221</id><published>2009-03-01T01:12:00.001+08:00</published><updated>2009-03-21T20:47:04.132+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Blog'/><title type='text'>在 blog 貼程式碼使用 Syntaxhighlighter + PreCode</title><content type='html'>&lt;h3&gt;前言&lt;/h3&gt;  &lt;p&gt;在上一篇教學後，我們已經可以使用 Syntaxhighlighter 來幫我們排版、美化程式碼了，不過很快地我們就發現單靠 &amp;lt;pre&amp;gt; 去排版還是會遇到問題，當初我覺得可以靠 WLW plugin 解決，沒想到馬上就找到了一個不錯的與 Syntaxhighlighter 整合的 plugin ，不過可惜的是，目前它支援的語法是 Syntaxhighlighter 1.5 的，不過好在有一些間接的 solution 。&lt;/p&gt;  &lt;p&gt;這個 plugin 叫做 PreCode ，有趣的是官網稱 PreCode 是 Code Snippet With Syntaxhighlighter Support for Windows Live Writer，而 PreCode 這名字只出現在 binary 中，啊，題外話。&lt;a href="http://precode.codeplex.com/"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;安裝 PreCode&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://precode.codeplex.com/" target="_blank"&gt;PreCode 的官方網站&lt;/a&gt;， 在這裡可以找到安裝檔，安裝很方便，安裝完後可以看到 WLW 視窗右方的工具列多出了一個 PreCode 的選項：&lt;/p&gt;  &lt;h3&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/SalwXycdMdI/AAAAAAAAAbA/9g_zhndBTc8/s1600-h/ScreenHunter_02%20Mar.%2001%2000.54%5B4%5D.jpg"&gt;&lt;img title="ScreenHunter_02 Mar. 01 00.54" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="368" alt="ScreenHunter_02 Mar. 01 00.54" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/SalwZC2omnI/AAAAAAAAAbE/FdY9dj6xbKM/ScreenHunter_02%20Mar.%2001%2000.54_thumb%5B2%5D.jpg?imgmax=800" width="468" border="0" /&gt;&lt;/a&gt; 使用 PreCode&lt;/h3&gt;  &lt;p&gt;PreCode 的使用相當直覺，點下 PreCode 後，就會跳出一個對話方塊：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/SalwaWvPovI/AAAAAAAAAbI/xsqAe6zInMU/s1600-h/ScreenHunter_06%20Mar.%2001%2000.58%5B3%5D.jpg"&gt;&lt;img title="ScreenHunter_06 Mar. 01 00.58" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="342" alt="ScreenHunter_06 Mar. 01 00.58" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/SalwbYVJF-I/AAAAAAAAAbM/h083ShnGnVI/ScreenHunter_06%20Mar.%2001%2000.58_thumb%5B1%5D.jpg?imgmax=800" width="484" border="0" /&gt;&lt;/a&gt; 對話方塊已經有 Content 區塊可以貼上程式碼，Format 則建議選擇 pre，Syntax Highlighting 的地方就根據需求設定吧！&lt;/p&gt;  &lt;h3&gt;跟 Syntaxhighlighter 2.0 共存&lt;/h3&gt;  &lt;p&gt;第一種方式是手動修改 HTML code ，如果把 PreCode 的產生的 HTML code 打開來看，你會看到：&lt;/p&gt;  &lt;pre class="brush: xml"&gt;&amp;lt;pre class=&amp;quot;cpp&amp;quot; name=&amp;quot;code&amp;quot;&amp;gt;#include &amp;amp;lt;iostream&amp;amp;gt;
using namespace std;

int main()
{
    cout &amp;amp;lt;&amp;amp;lt; &amp;quot;Hello World\n&amp;quot;;
    return 0;
}&amp;lt;/pre&amp;gt;&lt;/pre&gt;

&lt;p&gt;pre tag 的 class 的地方使用的是舊的 Syntaxhighlighter 語法，所以手動改成 “brush: cpp” 是一種方式。&lt;/p&gt;

&lt;p&gt;第二種方式是開啟 Syntaxhighlighter 的向下相容性，這個方法得修改 blog 的 template 檔，跟&lt;a href="http://keikoblog.blogspot.com/2009/03/blog.html" target="_blank"&gt;上一個教學&lt;/a&gt;一樣，只是得多加一行來啟動向下相容！&lt;/p&gt;

&lt;pre class="js" name="code"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
    SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/2.0.287/scripts/clipboard.swf';
    SyntaxHighlighter.all();
    dp.SyntaxHighlighter.HighlightAll('code'); // Add this!!!
&amp;lt;/script&amp;gt;&lt;/pre&gt;

&lt;h3&gt;參考&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://keikoblog.blogspot.com/2009/03/blog.html" target="_blank"&gt;在 blog 貼程式碼使用 Syntaxhighlighter&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-4307254228000037221?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/4307254228000037221/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=4307254228000037221' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4307254228000037221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4307254228000037221'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/03/blog-syntaxhighlighter-precode.html' title='在 blog 貼程式碼使用 Syntaxhighlighter + PreCode'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_2ZMoTkLFVu8/SalwZC2omnI/AAAAAAAAAbE/FdY9dj6xbKM/s72-c/ScreenHunter_02%20Mar.%2001%2000.54_thumb%5B2%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-97898674160058488</id><published>2009-03-01T00:13:00.001+08:00</published><updated>2009-04-26T18:41:46.880+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Blog'/><title type='text'>在 blog 貼程式碼使用 Syntaxhighlighter</title><content type='html'>&lt;h3&gt;前言&lt;/h3&gt;  &lt;p&gt;謠言都說 Web App 的時代來了，可是在 blog 上貼個好看的程式碼片段還是不太容易，以我自己的理解，一來是排版問題、 二來是語言有些符號和 HTML tag 相衝突，例如：C/C++ 的 &amp;lt; &amp;gt; 同時也用在 HTML tag 上，所以當我們寫下：&lt;/p&gt;  &lt;p align="center"&gt;#include &amp;lt;iostream&amp;gt; &lt;/p&gt;  &lt;p&gt;往往會導致 editor 把 iostream 當作HTML tag ，而導致發佈文章後，只看到：&lt;/p&gt;  &lt;p align="center"&gt;#include &lt;/p&gt;  &lt;p&gt;這是因為對於不認識的 tag ，解讀時是可以略過的，所以有些 editor 會在發佈時就清掉這些 tag。此外，為了美觀、可讀性，若是還能讓程式碼貼出後自動支援 syntax highlight 那就更好了！所以這邊就來介紹一個不錯顯示程式碼的好工具—— SyntaxHighlighter。&lt;/p&gt;  &lt;h3&gt;簡介&lt;/h3&gt;  &lt;p&gt;Syntaxhighlighter 是好心人 Alex Gorbatchev 利用 JavaScript 搭配 CSS、Flash 開發出來，使用上並不需要 blog host 在 server 端提供支援。不過需要另外的網路空間來存放 *.js, *.swf, *.css, *.png 檔，以前大家流行放在 &lt;a href="http://pages.google.com/" target="_blank"&gt;Google Page&lt;/a&gt; 這個免費空間上，不過這個服務去年八月就被 Google 收了，看似能取代 Google Page 的 &lt;a href="http://abin.azhai.org/2008/03/microsoft-skydrive-google-sites.html" target="_blank"&gt;Google Site&lt;/a&gt; 並不讓使用者上傳 js 檔。不過 Alex Gorbatchev 大概是好人作到底吧，他還提供了免費 host 的服務，至於頻寬問題怎樣，我就沒有細究了！&lt;/p&gt;  &lt;p&gt;Syntaxhighlighter 支援的語言很多，有&lt;a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter:Brushes:Bash" target="_blank"&gt;十六&lt;/a&gt;種：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Bash/shell &lt;/li&gt;    &lt;li&gt;C# &lt;/li&gt;    &lt;li&gt;C/C++ &lt;/li&gt;    &lt;li&gt;CSS &lt;/li&gt;    &lt;li&gt;Delphi &lt;/li&gt;    &lt;li&gt;Diff &lt;/li&gt;    &lt;li&gt;Groovy &lt;/li&gt;    &lt;li&gt;JavaScript &lt;/li&gt;    &lt;li&gt;Java &lt;/li&gt;    &lt;li&gt;PHP &lt;/li&gt;    &lt;li&gt;Plain Test &lt;/li&gt;    &lt;li&gt;Python &lt;/li&gt;    &lt;li&gt;Ruby &lt;/li&gt;    &lt;li&gt;SQL &lt;/li&gt;    &lt;li&gt;VB &lt;/li&gt;    &lt;li&gt;XML &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;而且支援六種顏色模式，可以&lt;a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter:Themes:Default " target="_blank"&gt;點這裡&lt;/a&gt;看到預覽：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Default：白色為主。 &lt;/li&gt;    &lt;li&gt;Django &lt;/li&gt;    &lt;li&gt;Emacs &lt;/li&gt;    &lt;li&gt;FadeToGrey &lt;/li&gt;    &lt;li&gt;Midnight &lt;/li&gt;    &lt;li&gt;RDark &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;另外，值得注意的是，沈寂了兩年，Syntaxhighlighter 才在今年二月初出了 2.0 版，不過與它相關的 plugin 似乎都還沒跟上腳步，所以想安裝 1.5 的人同樣可以參考這篇文章，方法是一樣的。&lt;/p&gt;  &lt;h3&gt;正文&lt;/h3&gt;  &lt;ol&gt;   &lt;li&gt;Syntaxhighlighter 可以在它 &lt;a href="http://code.google.com/p/syntaxhighlighter/" target="_blank"&gt;Google Code Syntaxhighlighter Project&lt;/a&gt; 或是 &lt;a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter" target="_blank"&gt;Alex Gorbatchev 的網站&lt;/a&gt;上找到。不過 2.0 目前只能在 &lt;a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter" target="_blank"&gt;Alex Gorbatchev 的網站&lt;/a&gt;下載到。（目前 &lt;a href="http://alexgorbatchev.com/downloads/grab.php?name=sh" target="_blank"&gt;2.0.287&lt;/a&gt; 是最新版） &lt;/li&gt;    &lt;li&gt;下載完，解壓縮可以看到幾個檔案和資料夾：      &lt;br /&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/SaliiR-BFuI/AAAAAAAAAa4/K7NjAjrHDBE/s1600-h/ScreenHunter_01%20Feb.%2028%2023.44%5B6%5D.jpg"&gt;&lt;img title="ScreenHunter_01 Feb. 28 23.44" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="180" alt="ScreenHunter_01 Feb. 28 23.44" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/SalijRaH6nI/AAAAAAAAAa8/m8hCKnlbBAU/ScreenHunter_01%20Feb.%2028%2023.44_thumb%5B4%5D.jpg?imgmax=800" width="484" border="0" /&gt;&lt;/a&gt;       &lt;ol&gt;       &lt;li&gt;scripts 資料夾下放著支援的程式語言相關的 JavaScript code。另外有個 clipboard.swf ，是 flash 元件，用來顯示程式碼、支援列印、複製等友善功能。 &lt;/li&gt;        &lt;li&gt;styles：css 檔。 &lt;/li&gt;        &lt;li&gt;src：不會用到。 &lt;/li&gt;        &lt;li&gt;test.html ：Syntaxhighlighter&amp;#160; 範例。 &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt;    &lt;li&gt;請找個網頁空間，上傳 Scripts、Styles裡頭的檔案。Scripts 裡頭的語言種類不一定要全放，選擇想要用的就可以了。找不到網路空間，可以去用 Syntaxhighlighter&amp;#160; 作者自己提供的。 &lt;/li&gt;    &lt;li&gt;修改 blog 的 template ，這步驟會根據你的 blogger host 而異。以 blogger 為例，請先登入再去範本 -&amp;gt; 修改 HTML，將下列程式片段貼到 &amp;lt;/body&amp;gt; &amp;lt;/html&amp;gt; 前。為免意外，請先備份原始 template 的程式唷。      &lt;br /&gt;      &lt;pre class="brush: xml;"&gt;&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shCore.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shLegacy.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushBash.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushCpp.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/shBrushCSharp.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushCss.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushDelphi.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushDiff.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushGroovy.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushJava.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushJScript.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushPhp.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushPlain.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushPython.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushRuby.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushScala.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushSql.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushVb.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;SCRIPT src=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/scripts/shBrushXml.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;
&amp;lt;LINK href=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/styles/shCore.css&amp;quot; type=&amp;quot;text/css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; /&amp;gt;
&amp;lt;LINK href=&amp;quot;http://alexgorbatchev.com/pub/sh/2.0.287/styles/shThemeDefault.css&amp;quot; type=&amp;quot;text/css&amp;quot; rel=&amp;quot;styleshee&amp;quot; /&amp;gt;
&amp;lt;SCRIPT type=text/javascript&amp;gt;
    SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/2.0.287/scripts/clipboard.swf';
    SyntaxHighlighter.all();
&amp;lt;/SCRIPT&amp;gt;&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;之後當你要貼上程式碼時，只要切換到 HTML 模式，然後用&amp;lt;pre&amp;gt;&amp;lt;/pre&amp;gt;框起程式碼的方式就可以了！ 
    &lt;br /&gt;

    &lt;pre class="brush: xml"&gt;&amp;lt;pre class=&amp;quot;brush: your_language&amp;quot;&amp;gt;
你的程式碼
&amp;lt;/pre&amp;gt;&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;最後是一個跟 WLW 有關的提醒，當我們切換到 WLW 的模式時，我們輸入的 &amp;lt;, &amp;gt;, &amp;amp; 等符號都不會自動轉換為對應的 &amp;amp;lt;, &amp;amp;gt;, &amp;amp;amp ，因此對於像是 C/C++ 這類語言來說，使用 SyntaxHighlighter 還是無法完全解決貼程式碼的問題，我想這點就必須倚賴 plug-in 來幫忙了！ 可參考&lt;a href="http://keikoblog.blogspot.com/2009/03/blog-syntaxhighlighter-precode.html"&gt;在 blog 貼程式碼使用 Syntaxhighlighter + PreCode&lt;/a&gt; 這篇文章！ &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;參考文章&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://keikoblog.blogspot.com/2009/03/blog-syntaxhighlighter-precode.html"&gt;在 blog 貼程式碼使用 Syntaxhighlighter + PreCode&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-97898674160058488?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/97898674160058488/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=97898674160058488' title='7 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/97898674160058488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/97898674160058488'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/03/blog.html' title='在 blog 貼程式碼使用 Syntaxhighlighter'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_2ZMoTkLFVu8/SalijRaH6nI/AAAAAAAAAa8/m8hCKnlbBAU/s72-c/ScreenHunter_01%20Feb.%2028%2023.44_thumb%5B4%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-5557783587041333795</id><published>2009-02-28T01:33:00.001+08:00</published><updated>2009-02-28T23:04:31.068+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Blog'/><title type='text'>用 WLW 寫 blog</title><content type='html'>&lt;p&gt;耶，這是篇拖了很久很久的教學文章，記得去年我要畢業前，好像答應要教 Alvin 老師，結果一暫且就…不過還好有 showmin 學長幫忙！不過文章還是不能欠啊，出來跑的，總有一天要還！&lt;/p&gt;  &lt;h3&gt;簡介&lt;/h3&gt;  &lt;p&gt;WLW 的全名是 Windows Live Writer ，所以很明顯的就是微軟出的，大家都喜歡訐詨微軟，不過不得不承認這家公司的編輯器都還不錯用，尤其和很多 blog host 提供的 editor 相比，更是好上很多，有時候真的會忍不住罵一下那些預設的 editor 是垃圾…ㄜ…我們好像是同業…&lt;/p&gt;  &lt;p&gt;那到底 WLW 有什麼好處呢？下面就讓我用&lt;font color="#0000ff"&gt;自身經驗&lt;/font&gt;，來個工商服務時間吧！&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;font color="#0000ff"&gt;離線編輯、&lt;font color="#0000ff"&gt;熟悉的編輯功能&lt;/font&gt;&lt;/font&gt;：沒錯，不要再相信沒有事實根據的謠言了！即使拔到獅子的鬃毛，號稱 Web 2.0 的 editor 也不會比 standalong 的桌面應用程式好用（好吧，我不否認，我討厭一股腦的把應用都丟在 web 的行銷和廣告）       &lt;br /&gt;基本上 WLW 很像 word 也很像 wordpad ，所以使用者可以很快速地上手，不會常常手滑，tab 按下去就回到上一頁了…       &lt;br /&gt;當然，快速鍵的支援、drag-and-drop 的功能更是沒有少，這可是身為桌面程式的驕傲唷 ^.&amp;lt; &lt;/li&gt;    &lt;li&gt;&lt;font color="#0000ff"&gt;不雞婆排版的編輯器&lt;/font&gt;：這可是最讓我激賞的一樣功能，WLW 是個&lt;font color="#0000ff"&gt;不雞婆排版的編輯器&lt;/font&gt;，這點對於貼程式碼是個很重要的能力，因為像是 blogger editor ，它總是會重新 layout 一下你的文章，然後你辛辛苦苦排好的文章就亂了！ &lt;/li&gt;    &lt;li&gt;&lt;font color="#0000ff"&gt;貼圖方便&lt;/font&gt;：使用 WLW 貼圖會很方便，就像是在 Word 裡頭插圖一樣，WLW 會自動上傳到 blog host 提供的空間，比起許多 on line editor 需要先上傳等自訂連結來的方便，當然也可以用 drag-and-drop 囉。 &lt;/li&gt;    &lt;li&gt;&lt;font color="#0000ff"&gt;統一的編輯器&lt;/font&gt;：free blog host 很多，在這些廠商中跳來跳去的人也不少，雙棲、三棲、以至於 N 棲的人也很多，但是你只要學一套編輯器的使用，基本上就可以討生活了，因為 WLW 允許你註冊多個 blog 帳號來使用。 &lt;/li&gt;    &lt;li&gt;&lt;font color="#0000ff"&gt;豐富外掛&lt;/font&gt;：很多人推薦這項功能，不過我自己很少用，而且至今我還是沒看過好用的貼程式碼外掛，這時候就很想抱怨了！blog 對程式設計師真的很不友善，可是，它們卻是程式設計師寫出來的…       &lt;br /&gt;為什麼無名相簿美女牆都有人做了，就是沒有人要作一個 programmer-friendly 的編輯器，好吧，因為大家都跟我一樣只會抱怨 –,- &lt;/li&gt;    &lt;li&gt;&lt;font color="#0000ff"&gt;強大的預覽功能&lt;/font&gt;：雖然還在開發階段，而且我自己很好使用，但是每次改版都可以感受到 WLW 預覽功能的進步！令我訝異的是，它竟然已經可以支援 embedded object 的執行，以下圖為例，當我們嵌入 youtube object ，WLW 已經允許你執行它了。這在前幾版是會有問題的，不愧是有 browser 技術的公司啊～ &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/SalSeTcmCSI/AAAAAAAAAas/X_BtZPXgJmA/s1600-h/image3%5B3%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="228" alt="image" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/SaghfNNmpsI/AAAAAAAAAaw/dV_AkUbJk-g/image3_thumb%5B2%5D.png?imgmax=800" width="208" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;為了怕被抹紅，說我是微軟同路人，這邊也要講一些 WLW 的缺點：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;font color="#0000ff"&gt;表格功能不&lt;/font&gt;強：WLW 的表格幾乎說只能提供設定外框、拉出 NxM 的樣式，或許對一般人夠用了，不過當遇到工程師這種愛畫表格比較功能時，就有點麻煩了，因為像是合併欄位、調整大小等細部的控制，WLW 做的不是很好，所以我的習慣是會用 &lt;a href="http://www.moztw.org/nvu/" target="_blank"&gt;nvu&lt;/a&gt; 這類網頁編輯器去製作好表格，然後再開啟 WLW 的 HTML 模式來加上複製。 &lt;/li&gt;    &lt;li&gt;&lt;font color="#0000ff"&gt;無法用滑鼠準確的調整圖片大小&lt;/font&gt;，你會發現當你放開滑鼠左鍵時，圖片還是會持續擴大一點，需要花點時間習慣，或是放棄直接調整圖片屬性。 &lt;/li&gt; &lt;/ol&gt;  &lt;h3&gt;下載&lt;/h3&gt;  &lt;p&gt;WLW 的官方網頁在：&lt;a title="http://windowslivewriter.spaces.live.com/" href="http://windowslivewriter.spaces.live.com/"&gt;http://windowslivewriter.spaces.live.com/&lt;/a&gt; 或是安裝惡名昭彰的 wlsetup 時，也會有選項可以讓你安裝。&lt;/p&gt;  &lt;h3&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/Saghf8mU9DI/AAAAAAAAAXk/A9j0Oy9hUio/s1600-h/ScreenHunter_01%20Feb.%2027%2023.54%5B2%5D.jpg"&gt;&lt;img title="ScreenHunter_01 Feb. 27 23.54" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="244" alt="ScreenHunter_01 Feb. 27 23.54" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/SaghgqsAtzI/AAAAAAAAAXo/Z9bpRTdtCDU/ScreenHunter_01%20Feb.%2027%2023.54_thumb.jpg?imgmax=800" width="164" border="0" /&gt;&lt;/a&gt; 設定&lt;/h3&gt;  &lt;ol&gt;   &lt;li&gt;     &lt;div align="center"&gt;安裝好後，第一次執行會跳出像是下圖的精靈，引導使用者設定他的 blog 進 WLW。微軟當然是力推 Windows Live Space ，不過不用擔心，主流的 Blog host 它也都是支援的，點選&lt;font color="#ff0000"&gt;其他的部落格服務&lt;/font&gt;就可以了。         &lt;br /&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/SaghhT8g9JI/AAAAAAAAAZs/l0nnPmaDvcs/s1600-h/ScreenHunter_02%20Feb.%2027%2023.57%5B6%5D.jpg"&gt;&lt;img title="ScreenHunter_02 Feb. 27 23.57" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="305" alt="ScreenHunter_02 Feb. 27 23.57" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/SaghiTlb21I/AAAAAAAAAZw/ylowBKeSlXQ/ScreenHunter_02%20Feb.%2027%2023.57_thumb%5B4%5D.jpg?imgmax=800" width="351" border="0" /&gt;&lt;/a&gt; &lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;接著會請你輸入你 blog 的網址、帳號、密碼等，就老實輸入吧！      &lt;br /&gt;      &lt;br /&gt;&lt;img title="ScreenHunter_03 Feb. 27 23.57" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="304" alt="ScreenHunter_03 Feb. 27 23.57" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/SaghkOuT-lI/AAAAAAAAAaE/H-yua0P9XWs/ScreenHunter_03%20Feb.%2027%2023.57_thumb%5B5%5D.jpg?imgmax=800" width="348" border="0" /&gt; &lt;/li&gt;    &lt;li&gt;當你輸入正確的資訊後，WLW會開始分析你使用的 blog 、blog 的樣式，然後嘗試發一篇測試文章到 blog ，這篇測試文章會自動被刪除！      &lt;br /&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/SaghlG4qXkI/AAAAAAAAAaM/Q7gSvD6viUE/s1600-h/ScreenHunter_04%20Feb.%2027%2023.58%5B4%5D.jpg"&gt;&lt;img title="ScreenHunter_04 Feb. 27 23.58" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="302" alt="ScreenHunter_04 Feb. 27 23.58" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/SaghmeiTdkI/AAAAAAAAAaQ/yU440V-x49Y/ScreenHunter_04%20Feb.%2027%2023.58_thumb%5B2%5D.jpg?imgmax=800" width="351" border="0" /&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;一切都成功後，就為你的設定檔取個名字吧，通常就是以 blog 名稱為預設名稱。      &lt;br /&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/SaghnGm4j8I/AAAAAAAAAac/fH5HO6IuwHw/s1600-h/ScreenHunter_06%20Feb.%2028%2000.03%5B4%5D.jpg"&gt;&lt;img title="ScreenHunter_06 Feb. 28 00.03" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="303" alt="ScreenHunter_06 Feb. 28 00.03" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/SaghoYUpdgI/AAAAAAAAAag/lFtTf-xN21M/ScreenHunter_06%20Feb.%2028%2000.03_thumb%5B2%5D.jpg?imgmax=800" width="351" border="0" /&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;成功後，便可以進入 WLW ，可以到工具，看一下你剛輸入的帳號資訊，之後你輸入的所有帳號也可以在這邊查詢、設定。      &lt;br /&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/Saghozbqq4I/AAAAAAAAAYM/OEoou9BNCqw/s1600-h/ScreenHunter_08%20Feb.%2028%2000.15%5B2%5D.jpg"&gt;&lt;img title="ScreenHunter_08 Feb. 28 00.15" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="117" alt="ScreenHunter_08 Feb. 28 00.15" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/SaghpZwI_4I/AAAAAAAAAYQ/WK2q6zP4V-0/ScreenHunter_08%20Feb.%2028%2000.15_thumb.jpg?imgmax=800" width="203" border="0" /&gt;&lt;/a&gt;&amp;#160; &lt;/li&gt;    &lt;li&gt;大家如果有些不錯的 plug-in 也不要忘了分享啊！ &lt;/li&gt;    &lt;li&gt;     &lt;div align="left"&gt;這邊附帶提一點，WLW 有個功能叫做類別，它相當於 blogger 裡頭的標籤，可以方便大家做文章分類。        &lt;br /&gt;        &lt;br /&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/SaghqCuLfQI/AAAAAAAAAYU/Rhtw5XA-T_Q/s1600-h/image%5B9%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="336" alt="image" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/Saghq0_OMDI/AAAAAAAAAYY/wxjtPjyhrUk/image_thumb%5B3%5D.png?imgmax=800" width="198" border="0" /&gt;&lt;/a&gt; &lt;/div&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;hr /&gt;  &lt;p&gt;講這麼多了，來偷看一下 blogger 的編輯器吧！&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/Saghr65sk0I/AAAAAAAAAYc/DfWe7uYHbOo/s1600-h/image%5B13%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="273" alt="image" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/Saghsu4QwEI/AAAAAAAAAYg/eiYx-Ep8NjA/image_thumb%5B5%5D.png?imgmax=800" width="364" border="0" /&gt;&lt;/a&gt; 唉，加油，好嗎？&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-5557783587041333795?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/5557783587041333795/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=5557783587041333795' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5557783587041333795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5557783587041333795'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/02/wlw-blog_28.html' title='用 WLW 寫 blog'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_2ZMoTkLFVu8/SaghfNNmpsI/AAAAAAAAAaw/dV_AkUbJk-g/s72-c/image3_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-3947232287215665922</id><published>2009-02-27T01:29:00.001+08:00</published><updated>2009-02-28T23:08:00.863+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><category scheme='http://www.blogger.com/atom/ns#' term='音樂歌曲'/><title type='text'>Mr. Adults</title><content type='html'>&lt;p align="center"&gt;這是 Mr. Children 的 Mr. Adults MV。 &lt;/p&gt;  &lt;hr /&gt;  &lt;br /&gt;&lt;center&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/mqlZVBcs1Wg&amp;amp;hl=zh_TW&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/mqlZVBcs1Wg&amp;amp;hl=zh_TW&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/center&gt;  &lt;p align="center"&gt;&lt;/p&gt;  &lt;hr /&gt;  &lt;p&gt;喂～ Kurumi    &lt;br /&gt;這街道的景色在你的眼中是什麼模樣呢？現在的我看起來又是怎樣？     &lt;br /&gt;喂～ Kurumi     &lt;br /&gt;若是旁人的關心也讓你聽起來像挖苦似的&amp;#160; 那個時候又該怎麼做才好呢？     &lt;br /&gt;只是回想起過去美好的一切&amp;#160; 卻讓人的心情更自覺得瀕老     &lt;br /&gt;在這樣的生活裡頭&amp;#160; 如今&amp;#160; 我正要動起來了     &lt;br /&gt;因為我不想只做個齒輪而已啊&amp;#160; 伴隨希望的衍生而增加的失望     &lt;br /&gt;即使如此明天的內心依舊悸動&amp;#160; 「究竟會發生什麼事呢？」     &lt;br /&gt;試著去想像看看吧     &lt;br /&gt;喂～ Kurumi     &lt;br /&gt;假使時間的河流會將一切給洗刷帶走的話&amp;#160; 那生存這件事就變得再容易不過了     &lt;br /&gt;喂～ Kurumi     &lt;br /&gt;在那之後我一次也不曾讓眼淚流下來&amp;#160; 可是&amp;#160; 讓我能夠開懷真心的笑卻也很少     &lt;br /&gt;不知在哪裡扣錯了&amp;#160; 發覺到的時候才知道多了一個鈕扣     &lt;br /&gt;就像這樣地要是能和某個有多的鈕扣穴的人相遇     &lt;br /&gt;讓一切變得有意義就好了&amp;#160; 伴隨邂逅的次數而增加的別離     &lt;br /&gt;即使如此內心仍因希望而跳動     &lt;br /&gt;每當在走過十字路口的時候&amp;#160; 難免也會有迷失方向的時候     &lt;br /&gt;總是乞望想擁有比眼前更多&amp;#160; 為了追求那不變的愛而高歌     &lt;br /&gt;於是齒輪不停轉動     &lt;br /&gt;超過必要的負擔 讓齒輪一面發出嘎吱的聲響     &lt;br /&gt;伴隨希望的衍生而增加的失望&amp;#160; 即使如此明天的內心依舊悸動     &lt;br /&gt;「究竟會發生什麼事呢？」 試著去想像看看吧     &lt;br /&gt;伴隨邂逅的次數而增加的別離&amp;#160; 即使如此內心仍因希望而跳動     &lt;br /&gt;現在已經不能夠回頭了啊&amp;#160; 向前走吧 踏上沒有你的這條路&lt;/p&gt;  &lt;hr /&gt;  &lt;blockquote&gt;   &lt;p&gt;話不要說得太絕！&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;哈，沒想到這句話今天要用在我身上了，以前我就很討厭那種充滿歌詞跟 MV 的 blog （我絕對不是在說我&lt;a href="http://kane-tomelf.blogspot.com/" target="_blank"&gt;同事 kane 哥&lt;/a&gt;），沒想到今天我卻要破例了，沒有為什麼，只是因為 fu 對了，有感而發…&lt;/p&gt;  &lt;p&gt;今天為了 team 上的 study group 在跟投影片奮戰，但是當耳機傳來 Mr. Adults 時，Mr. Adults MV 的畫面突然浮現腦海，情不自禁的就把視窗切到瀏覽器去了。有點心有慼慼焉…&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Hey～Keiko      &lt;br /&gt;這段 code 在你的眼中是什麼模樣呢？現在的我看起來又是怎樣？       &lt;br /&gt;Hey～Keiko       &lt;br /&gt;若是努力的維持軟體相容性也讓你聽起來像一成不變似的       &lt;br /&gt;那個時候又該怎麼做才好呢？ 只是回想起過去美好的一切       &lt;br /&gt;卻讓人的心情更自覺得瀕老&amp;#160; 在這樣的生活裡頭&amp;#160; &lt;br /&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;一直以來，受限於向下相容性以及穩定性，我們總是要捨棄一些堅持，其實不是很喜歡這樣作，但或許這就是工作的無奈，與學校不同，我們無法總是將認為最好的呈現出來，不過，我們也得學著不再任性，是的，任性的年代已經過去了…&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;如今&amp;#160; 我正要動起來了&amp;#160; 因為我不想只做個齒輪而已啊      &lt;br /&gt;伴隨希望的衍生而增加的失望&amp;#160; 即使如此明天的內心依舊悸動       &lt;br /&gt;「究竟會發生什麼事呢？」&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;儘管如此，我還是幸運的，總是在我心灰意冷、重頭喪氣時，有&lt;a href="http://fruitfoxlu.blogspot.com/" target="_blank"&gt;小路學長&lt;/a&gt;在旁邊，陪我聊天、開導我，每次跟小路學長談完話，我的熱情、滿腔熱血總是會再次燃起，好像以前我會跟 showmin、文森、DNA 去黑輪攤暢談一樣。&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;讓一切變得有意義就好了&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;當我們不能再任性時，是否這麼想就好了呢？讓一切變得有意義就好了，不要忘記自己的初衷、努力的原因！&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;每當在走過十字路口的時候&amp;#160; 難免也會有迷失方向的時候&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;所以一時的失落低潮、心灰意冷也只是暫時的迷失方向。&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;總是乞望想擁有比眼前更多&amp;#160; 為了追求那不變的愛而高歌      &lt;br /&gt;於是齒輪不停轉動&amp;#160; 超過必要的負擔&amp;#160; 讓齒輪一面發出嘎吱的聲響&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;目標既然已經明確，那就努力往前走吧，還有很多事在等著我們去做呢！&lt;/p&gt;  &lt;hr /&gt;  &lt;p&gt;今天報告完，很感謝 AEGIS team member 的肯定和鼓勵，讓我知道努力沒有白費，也很感謝同事 Allen 昨晚陪我奮戰到近十二點，只為了搞懂一些小細節和滿足我的龜毛。當然今天這美麗的夜晚要感謝小路學長，一時興起想去&lt;a href="http://tlsj.tenlong.com.tw/WebModule/index.do" target="_blank"&gt;天瓏&lt;/a&gt;買書，隨口邀了小路學長，沒想到他會答應，然後我們一直聊著、逛著到了高中生補完習要回家的九點半多，十年前，就在這個地方、這個時間，我也是在他們其中的一個，只是，現在我長大了！&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;現在已經不能夠回頭了啊&amp;#160; 向前走吧      &lt;br /&gt;「究竟會發生什麼事呢？」 試著去想像看看吧&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font color="#000000"&gt;對了，當然要最感謝我的 mentor Wesley Tsai ，不過他應該不知道這裡，所以就偷偷地感謝他過去三個月對我的教導，尤其感謝他的耐心，我總是忙著問他笨問題和出包，比較可惜的是，他今天請假沒來參加我的 present ，投影片可是我滿懷感激的心做出來的呢！&lt;/font&gt;&lt;/p&gt;  &lt;hr /&gt;  &lt;p&gt;今晚當然不是特別感性啊，只是因為我要跟試用期說 Byebye 了！&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/SabRggFIXsI/AAAAAAAAAXM/5gEmlGFFELc/s1600-h/x8OAFyds3VxPKyPDdH%2B2YCQRLRo%3D%5B3%5D.gif"&gt;&lt;img title="x8OAFyds3VxPKyPDdH 2YCQRLRo=" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="19" alt="x8OAFyds3VxPKyPDdH 2YCQRLRo=" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/SabRhLf4Q7I/AAAAAAAAAXQ/1jwC8zrHuIc/x8OAFyds3VxPKyPDdH%2B2YCQRLRo%3D_thumb%5B1%5D.gif?imgmax=800" width="19" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;我說：感性點不錯啊，難道要像下面那對一樣高調才好嗎？&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/SabSj72DZpI/AAAAAAAAAXU/EYqZynTeO6Y/image3.png?imgmax=800"&gt;&lt;img title="image_thumb1" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="243" alt="image_thumb1" src="http://lh5.ggpht.com/_2ZMoTkLFVu8/SabSmbq9K8I/AAAAAAAAAXY/g7zHAl3xVVM/image_thumb1%5B10%5D.png?imgmax=800" width="397" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-3947232287215665922?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/3947232287215665922/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=3947232287215665922' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3947232287215665922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3947232287215665922'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/02/mr-adult.html' title='Mr. Adults'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_2ZMoTkLFVu8/SabRhLf4Q7I/AAAAAAAAAXQ/1jwC8zrHuIc/s72-c/x8OAFyds3VxPKyPDdH%2B2YCQRLRo%3D_thumb%5B1%5D.gif?imgmax=800' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-1616627690852511801</id><published>2009-01-15T00:44:00.001+08:00</published><updated>2009-01-15T00:54:39.147+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>上工三個月了～</title><content type='html'>&lt;p&gt;時光飛逝、歲月如梭、韶光荏苒啊～雖然晚了一天，不過離去年 10/13 報到也過了三個月了，原本想來應應景、寫個試用期心得！沒想到前天 HR 跟我說：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;阿宅，醒醒吧，你記錯時間了，你要到 2/22 才過試用期！&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;不過，沒關係，這禮拜倒是發生了不少初體驗…&lt;/p&gt;  &lt;h3&gt;被扛霸子驚嚇&lt;/h3&gt;  &lt;p&gt;星期一大早寄出 Weekly Update，坐在我旁邊的老大馬上轉過頭問我一些實做上的細節，然後坐在老大後面的我們 team 的扛霸子馬上跳出來，&lt;/p&gt;  &lt;p&gt;扛霸子：你這樣不行啦～有沒有考慮過 ooxx？   &lt;br /&gt;Keiko：我們沒有這樣的 ooxx 的 case？（不知道為什麼，莫名心虛感油然而生）    &lt;br /&gt;扛霸子：怎麼會沒有？    &lt;br /&gt;Keiko：真的沒有！    &lt;br /&gt;扛霸子：啊～叫你們老大出來說啦～（台語）    &lt;br /&gt;老大：那你們開一個 meeting 討論吧～&lt;/p&gt;  &lt;p&gt;（以上對話為免泄露公司機密，所有對話經過修飾）&lt;/p&gt;  &lt;p&gt;meeting、meeting、開一個 meeting 就是要寫 document 的意思，還要用英文，好加在，在公司寫 document 的好處是，真的會有人看，不會越寫越無力，而且帶我的學長很願意幫我先看過！&lt;/p&gt;  &lt;h3&gt;大師兄回來了&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/SW4WEVptJMI/AAAAAAAAAWM/pn0ukcq2awE/s1600-h/image%5B24%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="143" alt="image" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/SW4WH7gc3sI/AAAAAAAAAWQ/lLl2cbXVrg0/image_thumb%5B16%5D.png?imgmax=800" width="194" border="0" /&gt;&lt;/a&gt; &lt;a href="http://lh5.ggpht.com/_2ZMoTkLFVu8/SW4WN82_R8I/AAAAAAAAAWU/RkQvwLz5pPk/s1600-h/image%5B17%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="140" alt="image" src="http://lh3.ggpht.com/_2ZMoTkLFVu8/SW4WRJr8zAI/AAAAAAAAAWY/TjG7AMm7TmM/image_thumb%5B9%5D.png?imgmax=800" width="209" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;星期一下午，也是我們 team 的小路學長就要歸建了，體貼的老大覺得小路東西（超）多，讓我去看看小路有沒有需要幫忙的地方，實在是揪甘心的，以後想找人討論東西、閒聊、假傳老師聖旨，就不必跑來跑去了，我還常常跑錯…&lt;/p&gt;  &lt;p&gt;當晚帶完新人去天瓏參觀後，就跑回公司跟義崧、小路吃晚餐，天啊，這時候深深發現 lab 的好處，大家系出同門，有問題都很好照應，什麼蠢問題、玩笑話都可以講的很自然，每次看到學長們變成 team 不可或缺的戰力，就很感佩，希望以後也有能貢獻自己心力的地方，不要老是扯後腿。&lt;/p&gt;  &lt;p&gt;PS. 什麼叫不可或缺的戰力呢？套句 DNA 學弟講的話，就像是：JM 跟時間在玩魔法風雲會，JM 只要說：這局我覆蓋小路卡或義崧卡，就可以獲得十回合的時間暫停！&lt;/p&gt;  &lt;h3&gt;Regular Meeting&lt;/h3&gt;  &lt;p&gt;我的老大很喜歡在 meeting 的時候，問大家問題，其中最常玩的把戲，大概就屬：光速思考吧！玩法是：&lt;/p&gt;  &lt;p&gt;這一秒，老大：有個問題我希望大家能好好思考一下，這很重要，關心到我們 team 的未來！   &lt;br /&gt;下一秒，老大：好，那個 xxoo ，你說說看！&lt;/p&gt;  &lt;p&gt;這禮拜的 meeting ，我馬上就被指名了 –,- 問題是你覺得 team 裡頭有什麼是你覺得欠缺的？&lt;/p&gt;  &lt;p&gt;我啦里拉雜的回答了，約莫是討論風氣、習慣的欠缺！但其實我知道有一半的原因是：我是晚進的新人，座位跟大夥隔著比較遠，而且身旁都是 manager 級的人，安安靜靜的工作環境還蠻正常的。不過我還是想提出來，算是給自己和大家的一個刺激和想法，還有點是因為我一直希望工作環境可以跟以前禹鴻、mobo 、小明在的 lab 一樣，有著很好的討論風氣，大家有什麼想法，都可以去“吵”一下對方！討論是我很熱於接受的、給程式設計師的 interrupt 和 context switch XD&lt;/p&gt;  &lt;h3&gt;寫出好的 document&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_2ZMoTkLFVu8/SW4WTSacNbI/AAAAAAAAAWc/8_vNGHaomgc/s1600-h/em-17%5B2%5D.gif"&gt;&lt;img title="em-17" style="border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; border-left: 0px; margin-right: auto; border-bottom: 0px" height="48" alt="em-17" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/SW4WVnenv2I/AAAAAAAAAWg/kXOG8HReKWo/em-17_thumb.gif?imgmax=800" width="48" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;雖然沒有一句話是這樣說的：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;寫出好的 document 帶你上天堂！&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;不過也沒有一句話是這樣講的：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Document 寫得好，要飯要到老！&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;所以，我一直很期待自己能寫出條理分明的文件或是投影片，為了準備跟扛霸子的 meeting ，孜孜矻矻寫了些 document ，還畫了 UML 的圖、補上自訂的圖形。沒想到換來不錯的效果， on board 以來沒主動跟我講過話的扛霸子，竟然主動叫了我的英文名字，還嚴守我堅持的發音（開口），讓我受寵若驚，走到曾經是禁區的扛霸子座位旁，看著他用樂高堆砌起的私人花園，更出乎意料之外的是，他竟然也用 Filco 鍵盤（茶軸），還用跟我一樣從 SCREAM Lab 走私出的 Grado Labs 耳機，然後討論完程式，還開始聊一下鍵盤、耳機等等初級敗家物。&lt;/p&gt;  &lt;h3&gt;C++ 神人&lt;/h3&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;不過最出乎意料之外的，還是該算今天發生的一件事…&lt;/p&gt;  &lt;p&gt;下午在改文件、灌新電腦的同時，想說也來偷偷收一下 gmail 吧，沒想到竟然有不認識的人回覆我 blog 的文章， ID 還是那麼地眼熟，不就是某某 C++ 神人嘛！天啊，他的 domain name 好像通訊錄上某個人，不過印象中，依稀記得神人去北京工作了，怎麼會…&lt;/p&gt;  &lt;p&gt;趕緊拉了大師兄跑去認人，哇靠，還真的是同一個人，天啊！&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;娘子，快跟牛魔王出來看神人啊～&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;好像在做夢唷，自己也都忘了跟他說了些什麼，只記得當時處在很亢奮的狀態，還好沒在神人面前鬼扯 C++ &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_2ZMoTkLFVu8/SW4WYtSBGZI/AAAAAAAAAWk/NpeCHcTRueo/s1600-h/2j9Wx1Sp0mWPLRTdYv2FZDv%2BLksg%3D%5B2%5D.gif"&gt;&lt;img title="2j9Wx1Sp0mWPLRTdYv2FZDv Lksg=" style="border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; border-left: 0px; margin-right: auto; border-bottom: 0px" height="100" alt="2j9Wx1Sp0mWPLRTdYv2FZDv Lksg=" src="http://lh6.ggpht.com/_2ZMoTkLFVu8/SW4WaYbKL-I/AAAAAAAAAWo/dDBFyWCI0Yw/2j9Wx1Sp0mWPLRTdYv2FZDv%2BLksg%3D_thumb.gif?imgmax=800" width="100" border="0" /&gt;&lt;/a&gt; 天啊，這實在是太酷了！回到座位上後，忍不住跟老大分享這個自以為是的、天大發現，沒想到老大只是冷冷地說：哈哈，這沒什麼，公司很多這種人，你以會還會遇到什麼什麼書的作者、bala bala&lt;/p&gt;  &lt;h3&gt;最後&lt;/h3&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;雖然上班後發現，每個禮拜維持兩篇 blog 文的產出實在是遙不可及（對不起，因為我很懶），不過今天還是想趕緊紀錄一下這分心情…&lt;/p&gt;  &lt;p&gt;開始瞭解小路學長當初在分享工作心得時，為何這麼說：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;在公司，要變成強者，只要有心，是遲早的事，但是重要的是與人相處的 EQ。（原文找不到，是憑映像打的！）&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;前半段是小路學長的“大丈夫當如是也”的自信，不過真的讓我很感動，公司有這麼多厲害的人，而且各有擅場、樂於分享！好希望、好希望自己也能學得他們幾分功力來自我滿足一下，工作三個月了，現在對自己的目標是也逐漸清晰起來了，總歸來說，還是跟進大學、念研究所時一樣：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;希望自己能作個有想法的人！&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;從小到大，總是會耳聞許多“強者我同學”的事蹟，雖然我不及他們，但還是希望自己能對感興趣的事物好好學習，理出自己一套想法，強者面前，即使真理多麼確立，能言之鑿鑿地和他們討論，那就是我能做的，如果還能讓他們思考或懷疑自己一下，哪怕只是一瞬，我也必定能有所得！&lt;/p&gt;  &lt;p&gt;囧，流水帳變八股勵志文了…那只好來搞笑一下，自從 regular meeting 發言，希望能增加 team member 間的討論風氣，沒想到，馬上就有人丟文章、連結跟我分享，實在讓我不好意思，看來一定是我平常太矜持了，沒發現其實大家就在旁邊，等著我去開場！&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-1616627690852511801?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/1616627690852511801/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=1616627690852511801' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/1616627690852511801'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/1616627690852511801'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/01/blog-post.html' title='上工三個月了～'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_2ZMoTkLFVu8/SW4WH7gc3sI/AAAAAAAAAWQ/lLl2cbXVrg0/s72-c/image_thumb%5B16%5D.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-3702133951834337328</id><published>2009-01-06T23:32:00.001+08:00</published><updated>2009-07-18T21:47:57.868+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Boost'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><title type='text'>為什麼 Boost 這麼大？</title><content type='html'>&lt;p&gt;今天 &lt;a href="http://kane-tomelf.blogspot.com/" target="_blank"&gt;kane 哥&lt;/a&gt;跟我說，Boost 編出來有 1 GB，想起來以前在醉資心也聽過有人這麼說…&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;那到底為什麼這麼大？&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;身為傳教士，當然不能回答說：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;你問我！我擲交！&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;這種答案可是天理不容啊～啊～啊～啊～&lt;/p&gt;  &lt;p&gt;套句聖主播說的話：揪竟~這個 boost 的背後，又有什麼不為人知的血淚因緣呢？文章的第一集，我們使用下面的指令來編譯：&lt;/p&gt;  &lt;p&gt;bjam.exe --build-dir=&amp;quot;your_dir\boost_1_35_0&amp;quot; --build-type=&lt;font color="#ff0000"&gt;complete&lt;/font&gt; --toolset=msvc install&lt;/p&gt;  &lt;p&gt;由於我們選擇 complete build type，所以 bjam 會產生出 12 個sublibrary，而 sublibrary 下又因為 vc 編譯組態可分為 single/multi-thread、dynamic/static link or debug/release mode、是否包含standard libary 四種不同，再檔名是否加上版本號碼的部份。算一算沒有七七四十九種，卻也大概一個 sublibrary 會有 18 種檔案。但檔案重複率很高就是了，像是下面以 Boost.DateTime 為例：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;18 個檔案只有 10 種版本&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;下面則是 Boost.DateTime 各版本的名稱及檔案大小，單項下內字體顏色一樣者表示檔案內容一樣（用 vim diff 測試）。 &lt;/p&gt;  &lt;table style="width: 471px; height: 876px; text-align: left" cellspacing="2" cellpadding="2" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td style="width: 85px; text-align: center"&gt;Linking Type&lt;/td&gt;        &lt;td style="width: 62px; text-align: center"&gt;Mode&lt;/td&gt;        &lt;td style="width: 246px; text-align: center"&gt;Name&lt;/td&gt;        &lt;td style="width: 189px; text-align: center"&gt;Size&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 85px; text-align: center" rowspan="6"&gt;Dynamic Link&lt;/td&gt;        &lt;td style="width: 62px" rowspan="3"&gt;Debug&lt;/td&gt;        &lt;td style="width: 246px"&gt;boost_date_time-vc80-mt-gd-1_35.dll          &lt;br /&gt;&lt;/td&gt;        &lt;td style="width: 189px"&gt;84.0 KB          &lt;br /&gt;(86,016 bytes)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 246px"&gt;&lt;font color="#ff0000"&gt;boost_date_time-vc80-mt-gd-1_35.lib            &lt;br /&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="width: 189px" rowspan="2"&gt;&lt;font color="#ff0000"&gt;26.6 KB            &lt;br /&gt;(27,278 bytes)&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 246px"&gt;&lt;font color="#ff0000"&gt;boost_date_time-vc80-mt-gd.lib&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 62px" rowspan="3"&gt;Release&lt;/td&gt;        &lt;td style="width: 246px"&gt;boost_date_time-vc80-mt-1_35.dll&lt;font color="#ff0000"&gt;            &lt;br /&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="width: 189px"&gt;48.0 KB          &lt;br /&gt;(49,152 bytes)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 246px"&gt;&lt;font color="#ff0000"&gt;boost_date_time-vc80-mt-1_35.dll&lt;/font&gt;&lt;font color="#ff0000"&gt;            &lt;br /&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="width: 189px" rowspan="2"&gt;&lt;font color="#ff0000"&gt;26.4 KB            &lt;br /&gt;(27,120 &lt;/font&gt;&lt;font color="#ff0000"&gt;bytes&lt;/font&gt;&lt;font color="#ff0000"&gt;)&lt;/font&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 246px"&gt;&lt;font color="#ff0000"&gt;boost_date_time-vc80-mt.dll&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 85px; text-align: center" rowspan="12"&gt;Static Link&lt;/td&gt;        &lt;td style="width: 62px" rowspan="6"&gt;debug&lt;/td&gt;        &lt;td style="width: 246px"&gt;&lt;font color="#ff0000"&gt;libboost_date_time-vc80-mt-gd-1_35.lib&amp;#160;&amp;#160; &lt;br /&gt;&lt;/font&gt;&lt;font color="#ff8000"&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="width: 189px" rowspan="2"&gt;&lt;font color="#ff0000"&gt;1.50 MB            &lt;br /&gt;(1,577,314 &lt;/font&gt;&lt;font color="#ff0000"&gt;bytes&lt;/font&gt;&lt;font color="#ff0000"&gt;)&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 246px"&gt;&lt;font color="#ff0000"&gt;libboost_date_time-vc80-mt-gd.lib&lt;/font&gt;&lt;font color="#008000"&gt;            &lt;br /&gt;&lt;/font&gt;&lt;font color="#ff8000"&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 246px"&gt;&lt;font color="#008000"&gt;libboost_date_time-vc80-mt-sgd-1_35.lib&amp;#160; &lt;br /&gt;&lt;/font&gt;&lt;font color="#ff8000"&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="width: 189px" rowspan="2"&gt;&lt;font color="#008000"&gt;1.66 MB            &lt;br /&gt;(1,747,582 bytes)&lt;/font&gt;&lt;font color="#008000"&gt;            &lt;br /&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 246px"&gt;&lt;font color="#008000"&gt;libboost_date_time-vc80-mt-sgd.lib&lt;/font&gt;&lt;font color="#ff8000"&gt;            &lt;br /&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 246px"&gt;&lt;font color="#ff8000"&gt;libboost_date_time-vc80-sgd-1_35.lib            &lt;br /&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="width: 189px" rowspan="2"&gt;&lt;font color="#ff8000"&gt;1.66 MB            &lt;br /&gt;(1,747,486 bytes)&lt;/font&gt;&lt;font color="#ff8000"&gt;            &lt;br /&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 246px"&gt;&lt;font color="#ff8000"&gt;libboost_date_time-vc80-sgd.lib&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 62px; text-align: center" rowspan="6"&gt;Release&lt;/td&gt;        &lt;td style="width: 246px"&gt;&lt;font color="#ff0000"&gt;libboost_date_time-vc80-mt-1_35.lib            &lt;br /&gt;&lt;/font&gt;&lt;font color="#ff8000"&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="width: 189px" rowspan="2"&gt;&lt;font color="#ff0000"&gt;523 KB            &lt;br /&gt;(535,964 &lt;/font&gt;&lt;font color="#ff0000"&gt;bytes&lt;/font&gt;&lt;font color="#ff0000"&gt;)&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 246px"&gt;&lt;font color="#ff0000"&gt;libboost_date_time-vc80-mt.lib&lt;/font&gt;&lt;font color="#008000"&gt;            &lt;br /&gt;&lt;/font&gt;&lt;font color="#ff8000"&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 246px"&gt;&lt;font color="#008000"&gt;libboost_date_time-vc80-mt-s-1_35.lib            &lt;br /&gt;&lt;/font&gt;&lt;font color="#ff8000"&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="width: 189px" rowspan="2"&gt;&lt;font color="#008000"&gt;661 KB            &lt;br /&gt;(677,130 &lt;/font&gt;&lt;font color="#008000"&gt;bytes&lt;/font&gt;&lt;font color="#008000"&gt;)&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 246px"&gt;&lt;font color="#008000"&gt;libboost_date_time-vc80-mt-s.lib&lt;/font&gt;&lt;font color="#ff8000"&gt;            &lt;br /&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 246px"&gt;&lt;font color="#ff8000"&gt;libboost_date_time-vc80-s-1_35.lib            &lt;br /&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="width: 189px" rowspan="2"&gt;&lt;font color="#ff8000"&gt;661 KB            &lt;br /&gt;(677,034 &lt;/font&gt;&lt;font color="#ff8000"&gt;bytes&lt;/font&gt;&lt;font color="#ff8000"&gt;)&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="width: 246px"&gt;&lt;font color="#ff8000"&gt;libboost_date_time-vc80-s.lib&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;例外，若是想瞭解這些檔案的命名規則，可以參考    &lt;br /&gt;&lt;a href="http://www.boost.org/doc/libs/1_35_0/more/getting_started/windows.html"&gt;http://www.boost.org/doc/libs/1_35_0/more/getting_started/windows.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;基本規則是這樣的：    &lt;br /&gt;[&lt;font color="#0000ff"&gt;prefix&lt;/font&gt;]boost_&lt;font color="#ff8000"&gt;sublibrary-name&lt;/font&gt;-&lt;font color="#008000"&gt;toolset-version&lt;/font&gt;-&lt;font color="#ff0000"&gt;options&lt;/font&gt;-[&lt;font color="#0080ff"&gt;version-number&lt;/font&gt;]&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;font color="#0000ff"&gt;prefix        &lt;br /&gt;&lt;/font&gt;lib 開頭代表 static link library ，沒有的則是 dll 和 import library &lt;/li&gt;    &lt;li&gt;&lt;font color="#ff8000"&gt;sublibrary-name&lt;/font&gt;&amp;#160; &lt;br /&gt;顧名思義 &lt;/li&gt;    &lt;li&gt;&lt;font color="#008000"&gt;toolset-version&lt;/font&gt;       &lt;br /&gt;顧名思義 &lt;/li&gt;    &lt;li&gt;&lt;font color="#ff0000"&gt;option&lt;/font&gt;       &lt;br /&gt;1. mt -&amp;gt; multithread       &lt;br /&gt;2. s&amp;#160; -&amp;gt; static link with C++ Standard Library &amp;amp; runtime library       &lt;br /&gt;3. d&amp;#160; -&amp;gt; sublibrary 的 code 有 debug information       &lt;br /&gt;4. g&amp;#160; -&amp;gt; C++ Standard Library &amp;amp; runtime library 都含 debug information &lt;/li&gt;    &lt;li&gt;&lt;font color="#0080ff"&gt;version number&lt;/font&gt;&amp;#160; &lt;br /&gt;boost 的 version number &lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-3702133951834337328?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/3702133951834337328/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=3702133951834337328' title='3 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3702133951834337328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3702133951834337328'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2009/01/boost.html' title='為什麼 Boost 這麼大？'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-7057169466228889550</id><published>2008-12-22T19:09:00.001+08:00</published><updated>2009-02-28T17:09:47.703+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><title type='text'>CreateProcess()</title><content type='html'>&lt;p&gt;今天下午在寫程式的時候被一個奇怪的問題給卡住，我寫的程式去呼叫 CreateProcess() 但一直跳出下面的錯誤訊息：&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://lh3.ggpht.com/_2ZMoTkLFVu8/SVIcw54NtiI/AAAAAAAAAVs/fa2GuVcTvow/s1600-h/ScreenHunter_02%20Dec.%2024%2019.07%5B3%5D.jpg"&gt;&lt;img title="ScreenHunter_02 Dec. 24 19.07" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="177" alt="ScreenHunter_02 Dec. 24 19.07" src="http://lh4.ggpht.com/_2ZMoTkLFVu8/SVIcx3hCI1I/AAAAAAAAAVw/ZzTAEgSjnME/ScreenHunter_02%20Dec.%2024%2019.07_thumb%5B1%5D.jpg?imgmax=800" width="361" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;原來問題出在我使用 Windows 的 CreateProcess() 這個 api 的方法錯誤，先來偷看一下 MSDN 的&lt;a href="http://msdn.microsoft.com/en-us/library/ms682425.aspx" target="_blank"&gt;函式原型&lt;/a&gt;：&lt;/p&gt;  &lt;pre class="brush: cpp" name="code"&gt;BOOL WINAPI CreateProcess(
  __in_opt     LPCTSTR lpApplicationName,
  __inout_opt  LPTSTR lpCommandLine,
  __in_opt     LPSECURITY_ATTRIBUTES lpProcessAttributes,
  __in_opt     LPSECURITY_ATTRIBUTES lpThreadAttributes,
  __in         BOOL bInheritHandles,
  __in         DWORD dwCreationFlags,
  __in_opt     LPVOID lpEnvironment,
  __in_opt     LPCTSTR lpCurrentDirectory,
  __in         LPSTARTUPINFO lpStartupInfo,
  __out        LPPROCESS_INFORMATION lpProcessInformation
);&lt;/pre&gt;

&lt;p&gt;其實問題的癥結很簡單，就出在第二個參數身上，為什麼 lpCommandLine 的型別是 LPTSTR 而不是 LP&lt;font color="#ff0000"&gt;C&lt;/font&gt;TSTR 呢？理由很簡單，因為系統會去更改這個參數，所以 MSDN 也用了 __in&lt;font color="#ff0000"&gt;out&lt;/font&gt;_opt 來修飾這個參數，因此我們不能傳一個 read only 的記憶體區塊到這個參數來。引用一下 MSDN 的說明：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;The &lt;font color="#ff0000"&gt;Unicode version&lt;/font&gt; of this function, &lt;/em&gt;&lt;a&gt;&lt;/a&gt;&lt;strong&gt;&lt;em&gt;CreateProcessW&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a &lt;/em&gt;&lt;strong&gt;&lt;em&gt;const&lt;/em&gt;&lt;/strong&gt;&lt;em&gt; variable or a literal string). If this parameter is a constant string, the function may cause an &lt;font color="#ff0000"&gt;access violation&lt;/font&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;有趣吧？！只有 Unicode 版本的 CreateProcess 會修改這個參數，所以下面的程式碼可以 work：&lt;/p&gt;

&lt;pre class="cpp" name="code"&gt;wchar_t cmd[ 100 ] = L&amp;quot;notepad D:\\mt.txt&amp;quot;; 
CreateProcessW( NULL, cmd, NULL, NULL, false, 0, NULL, NULL, &amp;amp;si, &amp;amp;pi ); 
CreateProcessA( NULL, &amp;quot;notepad D:\\mt.txt&amp;quot;, NULL, NULL, false, 0, NULL, NULL, &amp;amp;si, &amp;amp;pi );&lt;/pre&gt;

&lt;p&gt;但下面的程式碼是&lt;font color="#ff0000"&gt;不能 work&lt;/font&gt;：&lt;/p&gt;

&lt;pre class="brush: cpp" name="code"&gt;CreateProcessW( NULL, L&amp;quot;notepad D:\\mt.txt&amp;quot;, NULL, NULL, false, 0, NULL, NULL, &amp;amp;si, &amp;amp;pi );&lt;/pre&gt;

&lt;p&gt;是不是有點不 consistent 呢？&lt;/p&gt;

&lt;p&gt;此外，眼尖的人可能會發現為什麼一個 LPTSTR (即TCHAR*) 型別可以接受一個型別為 const TCHAR array 呢？C++ standard 2.13.4 不是這樣說的嗎？&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A string literal is a sequence of characters (as defined in 2.13.2) surrounded by double quotes, optionally beginning with the letter L, as in &amp;quot;...&amp;quot;or L&amp;quot;...&amp;quot;.&amp;#160; A string literal that does not begin with L is an ordinary string literal, also referred to as a narrow string literal.&amp;#160; &lt;font color="#ff0000"&gt;An ordinary string literal has type “array of n const char” and static storage duration&lt;/font&gt; (3.7), where n is the size of the string as defined below, and is initialized with the given characters. A string literal that begins with L, such as L&amp;quot;asdf&amp;quot;, is a wide string literal.&amp;#160; A wide string literal has type “&lt;font color="#ff0000"&gt;array of n const wchar_t” and has static storage duration&lt;/font&gt;, where n is the size of the string as defined below, and is initialized with the given characters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;font color="#000000"&gt;怎麼 VC++ 連個 warning 都不給呢？這是因為 C++ 為了相容於 C 所做出的讓步，來看一下 4.2&amp;#160; Array-to-pointer conversion 的描述：&lt;/font&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A string literal (2.13.4) that is not a wide string literal can be converted to an rvalue of type “pointer to char”; a wide string literal can be converted to an rvalue of type “pointer to wchar_t”.&amp;#160; In either case, the result is a pointer to the first element of the array.&amp;#160; This &lt;font color="#ff0000"&gt;conversion is considered only when there is an explicit appropriate pointer target type&lt;/font&gt;, and not when there is a general need to convert from an lvalue to an rvalue.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;因此，比較好的習慣是：總是用 const char/wchar_t* 去指向一塊 literal string。Scott Meyer 不就說了嗎？&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Use const whenever possible&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;: )&lt;/p&gt;

&lt;pre class="brush: cpp" name="code"&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;typeinfo&amp;gt;
using namespace std;

void foo( char* msg )
{
    cout &amp;lt;&amp;lt; &amp;quot;[foo( char* msg )] &amp;quot; &amp;lt;&amp;lt; msg &amp;lt;&amp;lt; endl;
}
void foo( const char* msg )
{
    cout &amp;lt;&amp;lt; &amp;quot;[foo( const char* msg )] &amp;quot; &amp;lt;&amp;lt; msg &amp;lt;&amp;lt; endl;
}

template&amp;lt;typename T&amp;gt;
void printType( T* x )
{
    cout &amp;lt;&amp;lt; &amp;quot;type of T: &amp;quot; &amp;lt;&amp;lt; typeid( T ).name() &amp;lt;&amp;lt; endl;
}

void badCall()
{
    throw &amp;quot;Exception&amp;quot;;
}

int main()
{
    foo( &amp;quot;Hello World&amp;quot; );
    printType( &amp;quot;Hello World&amp;quot; );

    try {
        badCall();
    }
    catch ( const char* msg ) {
        cerr &amp;lt;&amp;lt; &amp;quot;[const char* msg] &amp;quot; &amp;lt;&amp;lt; msg &amp;lt;&amp;lt; endl;
    }
    catch ( char* msg ) {
        cerr &amp;lt;&amp;lt; &amp;quot;[char* msg] &amp;quot; &amp;lt;&amp;lt; msg &amp;lt;&amp;lt; endl;
    }

    return 0;
}&lt;/pre&gt;

&lt;p&gt;我可沒說上面的 code 可以順利 compile 唷～&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-7057169466228889550?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/7057169466228889550/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=7057169466228889550' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/7057169466228889550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/7057169466228889550'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2008/12/createprocess.html' title='CreateProcess()'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_2ZMoTkLFVu8/SVIcx3hCI1I/AAAAAAAAAVw/ZzTAEgSjnME/s72-c/ScreenHunter_02%20Dec.%2024%2019.07_thumb%5B1%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-6549974776126648895</id><published>2008-12-18T22:29:00.001+08:00</published><updated>2008-12-18T22:29:55.532+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Boost'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><title type='text'>Boost.Test 的新文件</title><content type='html'>&lt;p&gt;&lt;a href="http://www.boost.org/users/news/version_1_37_0" target="_blank"&gt;Boost 1.37.0&lt;/a&gt; 也出了好一陣子了，不過公司不比實驗室，總是不能隨意看有興趣的東西，指派的工作或 reading 還是得擺在第一位，更何況直屬老闆跟大頭都做我後頭和旁邊，有時還是會有點壓力！&lt;/p&gt;  &lt;p&gt;不過最近被指派一個工作，跟 unit test 有關，趁著機會有時間可以看看新的 Boost.Test ，不過好像有點囧，怎麼 document 好像越寫越爛了…是我英文太爛嗎？還好舊電腦上還有舊版的 Boost.Test Doc ！&lt;/p&gt;  &lt;p&gt;哎呀，這個…程式設計師果然很討厭寫 document…果然古今中外都是…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-6549974776126648895?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/6549974776126648895/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=6549974776126648895' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/6549974776126648895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/6549974776126648895'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2008/12/boosttest.html' title='Boost.Test 的新文件'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-5161290257638581663</id><published>2008-11-29T17:16:00.001+08:00</published><updated>2008-11-29T17:16:27.749+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>下部隊了～</title><content type='html'>&lt;p&gt;在 11/21 (五) 也就是上個星期五，經過三天一連串的面試轟炸後，HR 大姐終於公佈了 TrendSchool 十二個人的未來落腳處了，我很幸運地來到了&lt;a href="http://fruitfoxlu.blogspot.com/" target="_blank"&gt;小路學長&lt;/a&gt;所在的 team ，當然上禮拜就感受到小路學長不離不棄的照顧，包括很多瑣事和我的白痴問題，只能說 SCREAM Lab 揪甘心，在家靠父母、出外靠 lab ！&lt;/p&gt;  &lt;p&gt;面試的過程，從面試官口中拋出的問題，除了用來刺激腎上腺素外，其實也是蠻好的學習發想，雖然面試前，總是會意思意思，給自己預演一下，想想可能會被問哪些問題，但大概除了自我介紹外，大概都很難命中吧，哈哈！&lt;/p&gt;  &lt;p&gt;身為一個研發替代役、偽軍人身份者，由於有三年役期關係，就被問了這樣的問題：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;你希望三年後，你能在工作上扮演怎樣的角色呢？&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;老實說，當這個問題丟出來後，我心頭先是一揪，然後就很想棄械投降了，因為我一直沒有好好想過這個問題，此外腦海中還一直浮現錢多、事少、位高權重、責任輕的玩笑話 -,- 的確進公司前只想先把技術好好扎實的學習，並未思考以後想扮演的角色，只好將以往在實驗室做計畫、研究、帶專題學弟等經驗拿出來講，分析一下以自己目前的能力可能對哪些職務工作可以勝任、哪些部份需要加強等。&lt;/p&gt;  &lt;p&gt;另外一個有趣的問題是：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;如果今天你的主管指派了一個重要工作給你？你覺得為什麼主管會找上你呢？若是今天一個你覺得可以勝任的工作，卻指派給一個你覺得無法勝任的人，而不是挑選你，你覺得是為什麼？&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;我想這種問題是有點人格特質的考驗嗎？面試官還一直叫我不要客氣，直說自己的想法，媽啊，面試官看出我在壓抑自己的思考，太恐怖了&amp;#8230;&lt;/p&gt;  &lt;p&gt;另外，還有兩個問題也是很值得思考，有點想是詢問你對工作責任的反應，但對我們這種剛畢業又被成功嶺摧殘大腦的新鮮人來講，還挺難的！&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;今天你突然接到一個緊急電話，說你寫的程式有問題，你當下會做怎樣的反應？另外，你覺得什麼是不能做的？&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font color="#000000"&gt;最後，這個問題也很恐怖，像是在幫你作生活態度檢討！&lt;/font&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;你覺得什麼時候應該跟你的主管報告進度？而哪時候不應該報告進度呢？&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;哈，上面講的都是讓我難以回答或覺得值得思考的問題，其實還有很多問題沒有列出來，面試三天，還有一個心得，就是面試官都相當厲害，除了要靈機應變化，還得去掌控面試的氣氛，尤其面對新鮮人，要能引導作答、替面試引進良好的談話氛圍，如此可以得到更多想要的答案！&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-5161290257638581663?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/5161290257638581663/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=5161290257638581663' title='8 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5161290257638581663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5161290257638581663'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2008/11/blog-post_29.html' title='下部隊了～'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-4123027650989755605</id><published>2008-11-17T23:54:00.001+08:00</published><updated>2008-11-17T23:54:59.927+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>2008 H2 Hi-Comm</title><content type='html'>&lt;p&gt;身為有很多活動的公司的一員，今天又再度參加公司辦的活動了，這次活動叫 Hi-Comm ，你知道、我知道、獨眼龍也知道，Hi-Comm 是某兩個英文單字的縮寫，不過似乎沒有人知道是哪兩個字&amp;#8230;我以為應該是 High-level Communication 的縮寫吧，因為會議上會看到很多好高高層，包括 CEO、 CCO、RD head 以及各個事業部的 director，還好這不是成功嶺，不用背誦長官名稱&amp;#8230;&lt;/p&gt;  &lt;p&gt;Hi-Comm 是每季或每半年都會舉辦一次的定期會議，由公司高層們主持，在台下聽的當然就是員工啦，主要是 RD、Sales、Marketing 三個部門， CEO 會說明過去一季的營運狀況以及新的一季的目標，同時也會跟大家講些生意上的好消息，像是誰誰誰變成我的客戶等等，這次還看到了坐鎮日本的 CFO 錄了一段影片給大家，還蠻搞笑的，這裡果然是間歡樂的公司，我也第一次領略了印度式英文，真是 so funny、so confused &amp;#8230;&lt;/p&gt;  &lt;p&gt;公司的大型會議通常會有一個特色&amp;#8212;&amp;#8212;很喜歡叫底下員工分組討論，然後由組長發表意見！這現象在公司三位 co-founders（Steve Chang, Jenny Chang, Eva Chen） 身上尤其常見，Steve 也就是張明正，通常會低著頭聆聽，然後發表自己的意見，意見多屬於 sales 方面的，並且會輔以一些過去的故事、Eva（陳怡樺）是個身材比例高挑的女生，RD 背景出身，哈，所以有時候講話格外親切（?!），而且也會適時得將 customer 放入談話內容中，很有自己的想法與意見，有趣的是，她講話時左腳會腳尖頂地，左手不時還會揮舞幾下，另外，她跟 Steve 一樣，是個很 high 的人&amp;#8230;&lt;/p&gt;  &lt;p&gt;Jenny（陳怡蓁）是公司的文化長（CCO，Chief Culture Officer），文化長做什麼呢？有人說就是辦活動的 XD 這解釋好像還蠻貼切，而且據說 Jenny 出現的場合，有獎金禮物可拿的機會就變多了 囧rz 其實從 Jenny 的談吐，感覺是個能過平凡生活就好、不喜歡行政管理的人，哈，不過誰叫她老公、妹妹這麼強咧！Jenny 的談話和 Steve、Eva 相比，顯得柔性親切，她會記得發言人的名字，並且試著以自己的話重複發言者的建議！&lt;/p&gt;  &lt;p&gt;哈，或許是身為新人吧，私心覺得這種活動似乎還不賴，不單是因為跑出來摸魚還有薪水拿 Orz&amp;#8230; 而是公司願意在決策時聆聽下面人的意見，雖然提出反對意見的效果會如何是不知道，但下場絕不會是壞的！從進公司的第一天開始，漂亮的人資小姐就幫我們上了半天的企業文化與願景，而後的會議中，也常聽到講者在強調願景。哈，羅蘭夫人說：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;自由，自由，多少的罪惡假汝之名而行﹗（O Liberty, Liberty, how many crimes are committed in thy name! ）&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;不知道可不可以改成：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;願景，願景，多少的洗腦假汝之名而行！&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;哈，這當然是開玩笑的！但從上個禮拜的 Engineering Camp 後，我就常在想，公司舉辦這些活動、高層們總是喜歡提願景，這些究竟可以對台下的人造成什麼影響呢？會不會把時間讓我們這些人去寫程式還比較有生產力呢？我沒有待過其它公司，不知道是不是每間公司都會找屬下來開這種會，而我確實相信願景可以帶給人們改變、確實是會讓所作所為帶來不同。幾次的討論中，不難發現真的有些人會對於問題提出自己的意見與看法，那都是他們幾經思考反芻的，而不是臨場的伶牙俐齒，原來公司裡頭真的有人在思考，而目前看來，公司也歡迎各種意見。&lt;/p&gt;  &lt;p&gt;再過三天就要填志願準備分發到 team 去了，一個多月的 TrendSchool 生活或許不夠真實感受一間公司的氣氛，但到了 team 就能比較真實嗎？還是只是反應了 team member 間的氣息呢？但至少應該會比在 TrendSchool 好，其實研發代替役的合約上，我們也是有試用期的，公司試用我們，我們也得試用一下公司啊～可惜的是，公司少了我，還有千千萬萬的阿宅工程師，但我卻只有成功嶺大饅頭&amp;#8230;&lt;/p&gt;  &lt;p&gt;一直想寫些介紹公司的文章，不過身為一個月新人，寫太好好像過度吹捧，又還沒真實經歷過，寫太糟，我就變成草莓族了&amp;#8230;&lt;/p&gt;  &lt;p&gt;想起兩個月前，Career 雜誌的專訪問說：選擇趨勢會不會後悔？&amp;#8230;兩個月前我連大頭兵都不是，實在無從悔恨起啊！不過現在不同了，希望下一個月後，沒有後悔來這研發替代役&amp;#8230;&lt;/p&gt;  &lt;p&gt;看待公司的政策措施其實是蠻有趣的，到底我們是勞資同舟共濟呢？還是壁壘分明呢？或許有時候，應該放下一個憤青的矜持，不要以拒絕表示自己的清高和與眾不同，有點矛盾、有點複雜，在這個世事無絕對，買安泰也不會比較好的時代，或許我們應該相信人性本善，先從認同做起，才能瞭解一件事物，進而將它放入心裡，想起大四去聽亞洲微軟研究院院長沈向洋的演講，他說：他最驕傲的一件事是，他的老師在他唸博士班的時候拿到 Turing Award，而不是他找了一個得了Turing Award 的人當指導老師！認同一個地方在幫助他成長永遠是一件美好的事！耶，不過我好像沒幫 SCREAM Lab. 寫出什麼驚天地、泣鬼神的論文或作品，囧rz&amp;#8230;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;PS. 其實這篇文章原本是要說明年（2009），趨勢又要開始舉辦程式競賽了！！這次不是百萬程式競賽，而是騰雲駕霧程式競賽（-,- 很有趣的名字），不過顧名思義就是針對 in-the-cloud computing 命題，賽前會有訓練課程，應該下個月就會有海報文宣了，希望有興趣的學弟妹們可以抽空參加！（不負責任說法：聽說組隊都是女生的話入闈機率會增加唷！）&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-4123027650989755605?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/4123027650989755605/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=4123027650989755605' title='6 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4123027650989755605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4123027650989755605'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2008/11/2008-h2-hi-comm.html' title='2008 H2 Hi-Comm'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-2004838419527159502</id><published>2008-11-13T23:00:00.001+08:00</published><updated>2008-11-13T23:01:44.215+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>一個月了</title><content type='html'>&lt;p&gt;哇，一個月了，當然不是交女朋友一個月了，更不是什麼分手失戀一個月&amp;#8230;是上班一個月了！這一個月過的很快，認識了很多朋友、前輩，也學到了很多東西（雖然大部分都是討人厭的網頁 -,-），原本打算寫點東西紀念一下，無奈在這麼有意義的一天，肚子在鬧脾氣，唉啊啊，轉眼看看blog 的 pending list 也積了很多文章，真不想說，沒列上去的還更多&amp;#8230;想講古虎爛的東西很多，時間卻很少，真是佩服那些技術底子深又能文章多產的大師們，今天的流水帳就到這，我要去床上躺平，台北的冷天氣，可是很適合睡覺的 : )&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-2004838419527159502?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/2004838419527159502/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=2004838419527159502' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/2004838419527159502'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/2004838419527159502'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2008/11/blog-post_13.html' title='一個月了'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-4073909190446701046</id><published>2008-11-05T12:18:00.001+08:00</published><updated>2008-11-05T12:25:27.518+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>請假拔牙</title><content type='html'>&lt;p&gt;沒想到上班不到一個月，就請了近半天假去看牙醫，真是始料未及，終究，又回到了要請假的年齡了!!不過擺脫惱人的智齒還真是令人愉悅啊！&lt;/p&gt;  &lt;p&gt;去的診所是從小看到大的，一家三代都給這醫生看過，醫生的手藝很好也很親切（醫生娘沒看過，所以就不附圖了），看著這診所從小變到大，簡陋到有裝潢（雖稱不上富麗堂皇），一路看來，只能說牙醫真好賺，我要做多久才能買自己的房子啊～老爸已經再問我的規劃了 -,- 你兒子才工作三個禮拜，又不是三年&amp;#8230;&lt;/p&gt;  &lt;p&gt;話說回來，這兩次看診的經驗還蠻特別的，醫生跟以前不太一樣，有點給人一種趕下班的感覺，雖然手還是很巧，但拔牙前後的叮嚀與搞笑橋段已經沒了，哈，看來是我已經變成大人了，醫生懶得跟我玩小時候那一套了 Orz &lt;/p&gt;  &lt;p&gt;想想，這醫生至少也在這開了二十年的診所，什麼樣的工作可以讓一個人做二十年？偉哉二十載，我才工作二十多天，就有幾天曾因為上班塞車而意興闌珊以致舉步維艱，竟然有人可以工作二十年、三十年、四十年，除了養家糊口之外，或許有些人一開始都有著自己的想法在，但能勿忘初衷而沒把自己賣給公司的能有多少呢？&lt;/p&gt;  &lt;p&gt;勿忘初衷！就像我對 web programming 的初衷就是黑特（hate），即使這幾天寫作業我假裝喜歡它，但現在想想：我還真是會騙自己&amp;#8230;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;我的初衷：&lt;/p&gt;    &lt;p&gt;I hate web programming&amp;#8230;     &lt;br /&gt;I hate script languages&amp;#8230;      &lt;br /&gt;I hate markup languages&amp;#8230;      &lt;br /&gt;Making humans edit XML is sadistic&amp;#8230;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;勿忘初衷，讓我想起以前在實驗室寫惱人的報告文件時，寫到恨意無法宣洩時，總會拿起幾本 C++ 的書來看，讚嘆一下、膜拜一下，讓我放下心中的恨&amp;#8230;&lt;/p&gt;  &lt;p&gt;勿忘初衷，讓我想到某屆學長們口耳相傳的、老師的一度口頭禪：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Every thing has a purpose. &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;有時候 purpose 就是你的初衷，要能不忘本意設計你的軟體總是很難，因為軟體的世界，總是佈滿有趣的叉路啊～&lt;/p&gt;  &lt;p&gt;勿忘初衷耶，幾乎每年的生日卡片上，我都會看到這句話，朋友總是在身旁提醒著我，揪甘心！雖然有時候會看成勿忘在莒 XD 但我相信，理想、堅持這類事，決不是一個人咬牙切齒就好的，就像電影霍元甲裡頭說著：&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;活著，從來都不是一個人的事一樣！&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;靠著家人、朋友的支持與幫助，我們才能走下去，理想與堅持也才有意義&amp;#8230;我們總是在從事服務業，服務自己、家人和朋友的人生！&lt;/p&gt;  &lt;p&gt;PS. 初衷也可以是賺錢 by 老爸 Orz...   &lt;br /&gt;PS2. 人老了，拔個牙都可以寫一堆有得沒得 Orz...&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-4073909190446701046?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/4073909190446701046/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=4073909190446701046' title='6 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4073909190446701046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4073909190446701046'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2008/11/blog-post_05.html' title='請假拔牙'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-3150426196336096795</id><published>2008-11-03T03:05:00.001+08:00</published><updated>2008-11-03T03:12:10.471+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>牙齒痛啊…</title><content type='html'>&lt;p&gt;原來牙齒痛是這種感覺，天啊，痛到睡不著了，喝了點溫水似乎可以舒緩一下，但馬上又痛起來了，一直含著溫水也不是辦法！明天還要上班、還有作業的 deadline，這一定是某種程度的報應吧！&lt;/p&gt;  &lt;p&gt;這個時間點真是尷尬又有趣，前兩天才拔掉另一顆蛀掉的智齒，早知道應該相信直覺，先拔現在在痛的這顆！&lt;/p&gt;  &lt;p&gt;抱著死馬當活馬醫的心態，上網 google 牙痛，竟然有人說用 10% 的漱口水漱口可以得到馬上舒緩，這真是太神奇了，可是我沒有漱口水，難道要衝下去小七買嗎？現在買兩罐還打五折 -__- 更神奇的是，有人說叩齒一千次，可以治好牙痛！！好吧，我要來開始叩齒數數了，效果怎樣？白天再跟大家分享&amp;#8230;&lt;/p&gt;  &lt;p&gt;智齒啊智齒，你的生長，我來不及參與；你的凋零我深刻感受到了&amp;#8230;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-3150426196336096795?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/3150426196336096795/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=3150426196336096795' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3150426196336096795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3150426196336096795'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2008/11/blog-post.html' title='牙齒痛啊…'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-922013335678681534</id><published>2008-10-29T22:29:00.001+08:00</published><updated>2008-10-29T22:29:27.521+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>破相了…</title><content type='html'>&lt;p&gt;開工兩個禮拜以來，差不多都是八點出頭就到公司，可以說是同梯裡頭最早到的，這當然不是因為勤勞，完全是因為怕塞車而已&amp;#8230;&lt;/p&gt;  &lt;p&gt;人家都說君子慎其獨，身為一個小人，閒居為不善，無所不至是我的天職。因此，我往往是人到了，放下早餐、放下書本，跑到遊樂室去玩投籃機或坐坐按摩椅，當然這種玩物喪志的生活，很快就帶來報應了&amp;#8230;&lt;/p&gt;  &lt;p&gt;今天投著投著，不知道怎麼回事，覺得渾身是勁，左手就出了過大的力，因此球出去的軌跡太高，打到了投籃機的鐵架，然後彈回來，好死不死正中右臉，眼鏡的鼻架就在右眼下留了一到傷痕，當然，小人也有小人的志氣，含著淚也得把一百球投完&amp;#8230;&lt;/p&gt;  &lt;p&gt;結果還不到五十球，隔壁部門的大姊姊來上班了，進來遊樂室倒水，害我很不好意思得趕緊跑去廁所整理一下狼狽樣，這大概就是小人見君子而後厭然吧&amp;#8230;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-922013335678681534?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/922013335678681534/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=922013335678681534' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/922013335678681534'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/922013335678681534'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2008/10/blog-post_29.html' title='破相了…'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-3955699568015384220</id><published>2008-10-26T00:53:00.001+08:00</published><updated>2008-10-26T01:07:45.578+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>我討厭搭公車上班</title><content type='html'>&lt;p&gt;開始上班了，上班就要通勤&amp;#8230; 公司的一切，在目前看來都很好，惟有工作的開始與結束，都讓我覺得很痛苦，因為要搭公車，滿滿的人，有時候在想公車會不會因此爆胎了&amp;#8230;&lt;/p&gt;  &lt;p&gt;身為偽台北國的一份子，每天認命早起搭公車進城是我的天職，第一天當然也不例外，等公車時，想起九年前的九月一日，那年我高一，九月一日是開學的日子，心理對於能搭公車上下學可是很高興的，因為從小對於重慶南路的書店就有股憧憬，暑假常吵著小阿姨帶弟弟和我去那打發時間，有時候，一個禮拜會去上三、四次，長大了，終於可以一個人坐車到那麼遠的地方了。&lt;/p&gt;  &lt;p&gt;不過現在不一樣了，從成功嶺回來後，我已經是個頂天立地、成熟穩重（？）的大人了，怎麼還會對能獨自出遠門上班高興，而且如今面對我的是恐怖的安康路，安康路是安坑對外的惟二聯外道路（分別到景美、中永和），雙向只有四線道，然後還要扣掉路邊停車、地下污水施工，已經跟兩線道相去不遠，可是、可是，光是安坑住了至少十萬人，到了新店市區還有十萬人，Orz，每天上班時刻，公車的乘車品質真的是很糟，沒有座位不說、有些人喜歡擠到你身旁搶扶桿、別人背的大包包會頂著你、背背包會變得很麻煩，容易頂到人、也容易擋路、有時候東西太多就會很麻煩，此外，上下班時間，公車一定是走走停停的，人家離人的歌詞是寫著：銀色小船搖搖晃晃彎彎懸在絨絨的天上，多美啊，我卻是：沙丁魚公車搖搖晃晃彎彎塞在坑坑洞洞的路上。況且，無論哪個時間點，總是很多人，早起有國中生、晚點有上班族，要想有個座位，大概要搭 6:20 ~ 6:50 左右的公車&amp;#8230;光是等公車，我就開始懷念過去六年住學校宿舍的從容悠閒了&amp;#8230;&lt;/p&gt;  &lt;p&gt;相信嗎？上班的兩個禮拜以來，我每天都在作紀錄，紀錄我每天上下車的時間：看是否可以得到某線公車在特定時段的的乘客數量；加上到公司的線有三個（根據行走路線，個別假設為短、中、遠三線），因此還得觀察三線公車前後七分鐘的互動，運氣好，先行的遠路線公車可以 cover 到慢行的短路線公車，至於怎麼預測遠程公車走後幾分鐘，會有短程公車呢？除了燒香拜佛，只能靠直覺了，總之，最後，我終於得到一個了上下班的好時間了&amp;#8230;&lt;/p&gt;  &lt;p&gt;所以我現在每天：   &lt;br /&gt;7:10 ~ 7:20 到公車站，搭乘無座位公車，約 8:10 買完早餐抵達公司座位    &lt;br /&gt;19:10 ~ 20:00 到公車站，搭乘有座位公車，約 20:10 到家&lt;/p&gt;  &lt;p&gt;寫完這篇文章，我發現我瘋了，竟然做起這麼無聊的事，唉，我想起小時候跟朋友說我喜歡坐公車的感覺，他們都說我瘋了，如今，事過境遷、物換星移，我終於討厭起公車了&amp;#8230;&lt;/p&gt;  &lt;p&gt;但寫完這篇文章，我也發現我當初沒有投內湖、汐止的公司是對的 Orz 那邊離我家更遠，而且還要換車，有一次去 water 學姐公司報告，我竟然花了兩個小時才到那&amp;#8230;&lt;/p&gt;  &lt;p&gt;寫著寫著，就想訐譙一下，我記得我國中還是高中時就看過政府在實驗公車到站時間的系統，幾年過去了&amp;#8230;連個影都沒看到，污水下水道系統也是，從我念碩士就開始挖馬路，挖到我都畢業了&amp;#8230;更扯的是，環快的中安大橋，從我要去台南念大學就開始建了，學士、碩士我都念到了，還沒建好，是不是要等我念個博士回來，才能看到它完工啊&amp;#8230;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-3955699568015384220?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/3955699568015384220/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=3955699568015384220' title='13 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3955699568015384220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3955699568015384220'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2008/10/blog-post.html' title='我討厭搭公車上班'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-4390441881899619147</id><published>2008-10-12T22:53:00.001+08:00</published><updated>2008-10-12T22:54:28.845+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ohana'/><title type='text'>回家的 fu</title><content type='html'>&lt;p&gt;換穿長褲、戴上帽子、出門買牛奶，才踏出大門，一種回家的感覺油然而生，買牛奶不用再等微波、牛奶買的是家庭號，所以不會在路上就喝完了、看到影音店還可以進去租片、出門前老爸不忘提醒幫買下酒花生和統一肉燥麵，原來這就是回家的感覺，平平凡凡的！&lt;/p&gt;  &lt;p&gt;然後，明天就要上班了！&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-4390441881899619147?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/4390441881899619147/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=4390441881899619147' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4390441881899619147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/4390441881899619147'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2008/10/fu.html' title='回家的 fu'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-3039122269273523154</id><published>2008-08-31T23:21:00.000+08:00</published><updated>2008-09-01T00:34:11.812+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><title type='text'>小朋友真可愛</title><content type='html'>&lt;p&gt;中午吃小火鍋時，隔壁桌坐著一對年輕夫妻外加他們的小女兒，妹妹長得很可愛，大約三、四歲吧，嘴裡吃著東西，還不忘東張西望。&lt;/p&gt;  &lt;p&gt;媽媽：妹妹啊，要不要吃豆皮啊？吃了可以變聰明唷，而且還可以變漂亮唷！   &lt;br /&gt;妹妹：漂亮，馬馬要讓我變漂亮啊～    &lt;br /&gt;媽媽：那要不要吃啊？    &lt;br /&gt;妹妹：不要！    &lt;br /&gt;媽媽：可以變漂亮，為什麼不吃啊？    &lt;br /&gt;妹妹：那妳要放在我這邊（指妹妹面前的鍋），這樣～這樣我才能吃啊，不然馬馬還要弄過來～    &lt;br /&gt;媽媽：那我把它放到巴巴鍋子裡，巴巴再夾給妳，好不好啊？（爸爸坐在女兒旁邊，共用一鍋）    &lt;br /&gt;妹妹：好啊～那我就要吃    &lt;br /&gt;Keiko：XD&lt;/p&gt;  &lt;p&gt;哈哈，養小孩真是一件辛苦又好玩的事，要他吃飯、做事要麼三催四請，要麼就連哄帶騙，不時還會聽到一堆搞笑、無回厘（音：ㄌㄧˊ）頭、令人噴飯的回答！而且，怎麼女生小小的就都已經知道什麼是漂亮不漂亮、美麗不美麗了？囧，我好像是到小二才開始能分辨男生、女生啊！至於怎麼分呢？找他/她玩變形金剛遊戲就知道了，肯跟我玩的就是男生，回答&amp;#8220;神經病&amp;#8221;、&amp;#8220;好無聊&amp;#8221;、&amp;#8220;我不要的&amp;#8221;就是女生啦 XD （我是奧托巴金剛，你是惡魔黨，進攻～ Orz ...）&lt;/p&gt;  &lt;p&gt;PS. 不知道以後，我會掰出什麼樣的理由騙我的小孩，我到底要不要讓我女兒知道男生其實是很邪惡的呢？&lt;/p&gt;  &lt;p&gt;PS. PS. 坊間書局不知道有沒有那種&amp;#8220;第一次，哄小孩就上手！&amp;#8221;、&amp;#8220;一百個讓小孩吃飯的連哄帶騙對話輯&amp;#8221;的書放在育兒區！小朋友區倒是可以放&amp;#8220;一百個不可不知爸媽讓小朋友吃飯的謊言&amp;#8221;&amp;#8230;&lt;/p&gt;  &lt;p&gt;PS. PS. PS. &lt;a href="http://keikoblog.blogspot.com/2008/08/blog-post_8039.html" target="_blank"&gt;噗哧學姐&lt;/a&gt;：你會不會想太多 -__-|| （學姐讓我有陰影了&amp;#8230;）&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-3039122269273523154?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/3039122269273523154/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=3039122269273523154' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3039122269273523154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/3039122269273523154'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2008/08/blog-post_31.html' title='小朋友真可愛'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-5203355839387169114</id><published>2008-08-30T01:07:00.001+08:00</published><updated>2008-09-01T00:46:07.555+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='雜七雜八'/><category scheme='http://www.blogger.com/atom/ns#' term='SCREAM Lab'/><title type='text'>噗哧學姐</title><content type='html'>&lt;p&gt;感傷完了，來講個有趣/機車的事好了&amp;#8230;&lt;/p&gt;  &lt;p&gt;由於周家有個離家六年的游子要歸來，周家老爺和夫人很高興地開始裝潢要給大少爺住的房間，還打了電話要這大少爺，想想看，心目中的房間，要生做怎樣？&lt;/p&gt;  &lt;p&gt;這大少爺不加思索地就說：我想要有 L 型的書桌，其他隨便！&lt;/p&gt;  &lt;p&gt;老爺、夫人：遵命！&lt;/p&gt;  &lt;p&gt;電話ㄧ掛掉，少爺馬上想到，房間已經有國二就做好的書桌了，要擺 L 型書桌進去，得打掉原本的東西，相當麻煩！而少爺冰雪聰明、乖巧懂事、善解人意，馬上又打了電話回去跟爹娘說：還是一切照舊就好，不用改了！&lt;/p&gt;  &lt;p&gt;為何呢？其實道理很簡單，因為少爺正值青春二十四，搞不好五年後就結婚了？搞不好就搬出去住了？搞不好要改成雙人房？搞不好是二少爺奉子成婚，大少爺得騰出房間&amp;#8230;太多的搞不好，但總之就是現在砍掉重練是不划算的&amp;#8230;&lt;/p&gt;  &lt;p&gt;這一切的一切，都由大少爺跟實驗室朋友在聊著，然後走在後頭的學姐，突然噗哧ㄧ生，大笑出來&amp;#8230;&lt;/p&gt;  &lt;p&gt;學姐：五年？會不會也太快了？還有你會不會想太多了啊，學弟？&lt;/p&gt;  &lt;p&gt;大少爺心中的 OS：女馬白勺，我就是行情差啦&amp;#8230;我杞人憂天&amp;#8230;我都說了是最快，妳想怎樣&amp;#8230;我馬上上 O2 徵一個給妳看&amp;#8230;不然烏克蘭也是有好女孩的&amp;#8230;&lt;/p&gt;  &lt;p&gt;故事說到這裡，大少爺已經惱羞成怒了&amp;#8230;&lt;/p&gt;  &lt;p&gt;還有我不會承認我就是大少爺&amp;#8230;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-5203355839387169114?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/5203355839387169114/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=5203355839387169114' title='5 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5203355839387169114'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/5203355839387169114'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2008/08/blog-post_8039.html' title='噗哧學姐'/><author><name>Keiko</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://1.bp.blogspot.com/_2ZMoTkLFVu8/SKhjVA8WBeI/AAAAAAAAAM4/4-fMkiEO35Q/S220/buddy_etonne.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9975629.post-2959998139638970241</id><published>2008-08-30T00:39:00.001+08:00</published><updated>2008-08-30T00:41:30.985+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SCREAM Lab'/><title type='text'>該來的總是要來…</title><content type='html'>&lt;p&gt;ByeBye ...&lt;/p&gt;  &lt;p&gt;終於，引頸企盼、千呼萬喚的畢業證書在今天（據說今天好像是辦離校的最後一天）到手了，經過了這麼多人的簽名，過程就像集點一般，奔走於校園內，好像把這兩年來逛校園該走的路都走完了，太陽公公也很機車地一直好奇地跟在我身後 -__-||&lt;/p&gt;  &lt;p align="center"&gt;看，畢業證書 Got!!!    &lt;br /&gt;&amp;#160;&lt;a href="http://lh5.ggpht.com/Keiko.Zhou/SLgmOXnDltI/AAAAAAAAARg/i-xeze-zSZQ/s1600-h/test%5B5%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="test" src="http://lh6.ggpht.com/Keiko.Zhou/SLgmPE2th9I/AAAAAAAAARk/LHn5yFxwCi4/test_thumb%5B1%5D.png?imgmax=800" width="182" border="0" /&gt;&lt;/a&gt;     &lt;br /&gt;（V 怪客是我最近的英雄！Beneath this mask there is more than flesh. Beneath this mask there is an idea, Mr. Creedy, and ideas are bulletproof.）&lt;/p&gt;  &lt;p&gt;拿了這張畢業證書後，我想再也沒有理由是讓我強迫性地留下了，以後的出現都是發自內心地想回來看看&amp;#8230;&lt;/p&gt;  &lt;p&gt;這個待了六年的大學、三年半的實驗室，我還記得當初想進 SCREAM Lab 的原因，老師記得要稱讚我初衷不忘啊～我也曾經迷惘過，專題是不是隨便就好？研究所是不是應該找個涼一點的老師？這樣我有很多時間可以做自己想做的事，直到我在趨勢競賽頒獎典禮上看到了小路和禹鴻。另外則是&amp;#160; mobo 學長，他是我高中社團的學長，雖然當時不太熟，但他也拿過趨勢競賽的名次，同時也是 Alvin 老師的研究生，所以我還一度以為進這實驗室，是不是都要先通過 trendmicro 的 QA 檢測 XD，而且還聽說 SCREAM Lab 裡頭有個叫義崧大魔頭。哈哈，那也就沒什麼好選的了，我從不期盼自己能做出偉大的研究，只希望自己能在程式撰寫中得到樂趣，這麼多高手前輩認可的實驗室，我不進來，難道我是笨蛋嗎？&lt;/p&gt;  &lt;p&gt;在詢問老師意見前，我對老師的印象只有大一電子電路課，老師是個跳 tone 大王，投影片跳來跳去，好不混亂 -_- 但有一天，老師帶了本天下雜誌（?!）進來，然後搬了一張學生的課桌椅坐下，整堂課就是在講台灣與韓國，談到產業、留學生等問題，哈，我這人最愛不務正業，看來這老師也很愛不務正業，喜歡聊天、感召學生。其實我ㄧ直都在想，我都唸大學了，知識都寫在課本上了，不是自己念舊好了嗎？為什麼得乖乖來上課呢&amp;#8230;所以我一向喜歡愛聊天的老師，因為那些講出口的經歷，才是課本沒有的&amp;#8230;&lt;/p&gt;  &lt;p&gt;專題前，為了更瞭解 SCREAM Lab ，我跑去修了老師的資料壓縮，還旁聽了一下 NN 。很快地，ㄧ學期的時間就快沒了，身旁的同學都已經找到專題指導教授，我這樣再龜下去也不是辦法，硬著頭皮跑去找老師。第一次果真是震撼教育，老師問我想做什麼？我講了很多，但都一一被婉轉化解，要嘛說這已經有了，要嘛說其他老師也有做之類的，總之一個整不想收我，囧rz 看來我是敗絮其外&amp;#8230;最後，老師請我回去想想，一個禮拜後再去找他&amp;#8230;&lt;/p&gt;  &lt;p&gt;一個禮拜過後，依稀記得是星期四下午五點十五分吧！我在老師門口觀望（老師也剛好不在），湊巧小路學長經過，閒聊中知道我想請 Alvin 老師做專題指導，便很熱心地說等會要幫我推薦，還陪我等了一下老師，哈哈，那時，我才跟小路學長碰不到五次面、講不到十句話過，學長是個好人，老師則是個好騙的人，因為那次之後，我就有了新身份： SCREAM Lab. 專題生！&lt;/p&gt;  &lt;p&gt;今天畢業了，老師給了我最後一個論文題目，那就是以後要健康快樂！健康快樂啊，SCREAM Lab 的大家，健康快樂啊，老師，謝謝你三年半來的放縱與教誨，學生很高興能成為 SCREAM Lab 的一員！&lt;/p&gt;  &lt;p&gt;明天就要回台北了，今晚是最後一次在 Lab 熬夜啦～ &lt;/p&gt;  &lt;p&gt;今晚之後，我就不是南國少年，周 NK 啦~&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9975629-2959998139638970241?l=keikoblog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keikoblog.blogspot.com/feeds/2959998139638970241/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9975629&amp;postID=2959998139638970241' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/2959998139638970241'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9975629/posts/default/2959998139638970241'/><link rel='alternate' type='text/html' href='http://keikoblog.blogspot.com/2008/08/blog-post_30.html' title='該來
