最近一堆病毒都是透過隨身碟的自動播放來執行與傳播的,其實微軟搞這個功能真的蠻煩人的,不如直接關掉。
關掉的方法如下:
執行 regedit,並修改 HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion
\Policies\Explorer\,把 NoDriveTypeAutoRun 的值改為 ff(16進位)或是 255(10進位),再重開機即可。(可參考下圖)
如果還搞不清楚,或嫌麻煩,可以直接下載 TurnOffAutoRun.reg,執行後再重開機即可。
2007年11月5日 星期一
2007年11月4日 星期日
馬英九並非斯德哥爾摩症患者
今天(2007/11/04)看到一則新聞,謝長廷批評馬英九像得了 "斯德哥爾摩症" 似的,大意是說馬英九最近的一些行為跟本是學民進黨或陳水扁那樣,拿香對拜,例如入聯/返聯、公投、發票報帳等事。
真不知道是哪個豬頭教他講的,這個比喻不倫不類,而且蠢到不行。不但會被反譏說謝長廷自己才是被綁架的人,而且也直接把自己陣營的陳水扁變成是 "綁匪"。總之這個比喻實在爛的離譜,跟本就是把自己的嘴送上去給人打巴掌。
純就選戰策略來說,要指控這種拿香對拜的行為,倒是有個蠻適合套在馬英九身上的例子:慕容復!
慕容復最出名的手法就是 "以彼之道,還施彼身",很多有看過天龍八部的人都知道,這是拿對手的招式打回去的手法。
以慕容復來指控馬英九的好處在於可以有一些有趣的類比:
2007年10月23日 星期二
釋夢人 - 三個怪夢及其解析
「釋夢人」是一本我去年看過的小說,其實與本文無關,只是借用其名,暫時充當自己的「釋夢人」。
昨天晚上,老婆跟我談了半天關於未來的生涯規劃的事,當然包括工作、發展。夜裡,我一如預期的失眠了,未來該怎麼走的問題其實在這一年來始終困擾著我。
最後一個夢印像最深,我從這個夢開始:夢中的主角是個女性,感覺上好像這個人就是我,又好像我只是透過她的眼睛在看世界。Anyway, 就用第一人稱來描述好了。我收到一束花,裝在花瓶裡,但之後送花的人就沒再出現,而我一直期待著他再次出現,夢中還有很多跟我有同樣情況的人。直到花 漸漸的謝了,我像其他女生一樣把花朵的部分剪了,留下枝幹,插在花瓶裡,每次只要往花瓶裡吹氣,就會聞到殘留的花香,藉些得到慰借。可是時間久了,不但沒 有人再送花來,而且很多人開始生病,我也是只中一個,喉嚨部位開始長了一些病灶,有些比較嚴重的人甚至死去了。我驚覺到這一定跟那瓶花有關,於是下定決心不再依賴它。我把花瓶仍了,並且尋求治 療。不知是醫務人員,還是我自己,在拿著注射針筒刺進我喉嚨時,我就醒了。
- 我認為收到花,代表了曾經的升職與加薪。
- 被剪去花朵,只留枝幹與與花瓶,表示隨著時間過去,這種待遇對我來講已經是不足夠的了。
- 想要再收到花卻遙遙無期,這也反應了公司現況:升遷變難了
- 但大多數人(包括我),仍然抱著那還有些餘香的花瓶捨不得離開,因為離職或轉換跑道的話又擔心待遇變差、甚至是年資重計,而待在原來的公司,好歹可以領個過的去的薪水
- 生病則像徵如果這情況繼續下去,不但離自己想要的生活或理想越來越遠,甚至以後真的就變電視新聞上的 "中年失業"。有些人甚至病死了,的確,就像那些已經失業,或是對理想完全放棄的人
- 把花瓶丟掉,並且開始尋求醫療,意謂著我已經正視這個問題,並且開始著手解決之道,至於以後會怎樣呢? 不知道,所以夢就醒了 :)
- 武術高手像徵對自己能力的自信
- 遙遙無期的等待,就好像現在在工作上,混一天算一天,卻擋不住心中的焦慮
- 我覺得泡在那個噁爛大池,就像我現在的情況一樣:跟一堆噁爛程式碼泡在一起,偶爾還要解些 bug,這些 bug 其實跟本都是別人拉的大便
- 至於我不願吞下的那些令人做嘔的東西,自然就是工作上常見的許多人都會有的便宜行事手法,這些方法解決了眼前的問題,實際上只是造成更多問題,我對這種手法的感覺一直就是 "噁心" 兩個字
- 很明顯的,有些人是很喜歡用這種手法的,而且還認為自己能做的到,沾沾自喜
- 而我當然無法接受,所以說「我才不要吃這種東西咧!」
- 第一個像徵我對現在工作處境的不滿
- 第二個夢一方面代表我對自己未來發展的焦慮,另一方面卻又一天混過一天
- 第三個夢更具體的表現出我的焦慮以及混日子的原因,最重要的是最後我開始正視問題了
2007年9月14日 星期五
2007年7月28日 星期六
依法行政
最近看到一些blog 與討論,讓我對所謂的依法行政有更深一層的了解,而事件的起源是北投纜車(還不是最近被罵到爆的貓空纜車)。
什麼是依法行政? 北投纜車鑽法律漏洞不執行環評就是馬前市長的口頭禪:依法行政!
跟據我國環評法規「開發行為應實施環境影響評估細目及範圍認定標準」第七條(第3-6款):「位於非都市土地,申請開發面積十公頃以上或擴建面積累積十公頃以上者」,「應實施環境影響評估」。
而北投纜車佔地面積多少? 9.972 公頃,真巧,是合法的耶! 可是會不會太巧了? 剛剛好低空飛過?
這是怎麼回事? 其實北投纜車開發面積原本是超過 10 公頃的,但超過 10 公頃就要做嚴格的環境影響評估,需要花較多的時間,這樣一定來不及成為馬市長任內的「政績」,因此市府就善用他們的對專業與法律的素養,把開發面積縮到 10 公頃以內。
那要怎麼做呢? 跟據「中華民國國家標準CNS5085號規範」,「北投纜車的路權寬度為15公尺」,簡單的說就是寬度是 15公尺。但這樣興建起來,開發面積就會超過 10 公頃,所以只好改而採用「中華人民共和國的纜車安全標準」,寬度只需要 11 公尺!! 開發總面積剛好塞進 10 公頃的範圍內,真是厲害!
原來所謂的依法行政還有這幾層意義:
1. 依法律漏洞行政
2. 依中國(某人的祖國?)法律行政
註1:資料來源為 謝明海先生在自由時報的文章
2007年7月24日 星期二
2007年7月22日 星期日
2012 年國民黨的正副總統人選
現在是 2007 年的七月,人人都知道 2008 年總統大選國民黨的正副總統參選人是誰(雖然有些人認為其簡稱有些不雅,念起來像肖告配),而民進黨的總統人選也已確定,副總統人選據說將在中秋節前決定。
但我現在要告訴大家,其實我連 2012 年國民黨會推的人選都知道了!
- 2000 年:連戰、蕭萬長、宋楚瑜、張昭雄
- 2004 年:連戰、宋楚瑜
- 2008 年:馬英九、蕭萬長
看到 2008 年時,應該很多人都注意到已經是連續兩屆有重覆的人選了。我們把所有的人都列出來看看:
- 連戰:兩次
- 蕭萬長:兩次
- 宋楚瑜:兩次
- 張昭雄:一次
- 馬英九:一次
答案應該很清楚了,正所謂不患寡而患不均,其實這擋子事是大家輪流玩的,不然至少也是 "雙淘汱賽",每個人有兩次機會。我在此大膽預測,下一次的人選一定是
2007年7月19日 星期四
黑心包子? 黑心新聞? 還是黑心政府?
2007年7月17日 星期二
在 VC IDE 的 Find/Replace 使用 Regular Expression
最近公司說要儘量把 compiler warnning 減到最少,在清理 warning 的過程中,我發現有一堆 warning 是來自像底下這種 code:
#define PI 3.14159
DSPfract p = PI;
會出現 warning C4305: 'initializing' : truncation from 'double' to 'float'.
先不談應該用 const variable 而不該用 #define PI 這種東西的問題,這個問題的關鍵是要讓 compiler 知道要以 float 來處理小數,像這樣:
#define PI 3.14159f
但這種地方很多,我可不想手動一個一個做,所以我打算直接在 Visual Studio IDE 中用 regular expression 來解決問題,regular expression 是我很不熟的東西,但做簡單的工作應該還不成問題。
先來看看該怎麼 find,小數就是一個連串的數字,後面緊接著一個小數點,然後再緊接著一連串的數字,所以我們寫 [0-9]+\.[0-9]+ 來尋找,果然還蠻順利的,但要記得勾選 match whole word。
尋找沒問題,接下來就是 replace 了。首先把 find 欄填的內容從 [0-9]+\.[0-9]+ 改成 ([0-9]+\.[0-9]+),用小刮號括起來表示這是一個 tag,等一下 replace 時會用到。接下來到 replace 欄位輸入 \1f,其中 \1 代表 find 的第一個 tag, 就是在 find 時 match 的字串。以此例來說,3.14159 就是我們的 tag 1,因此 \1f 就會被展開成為 3.14159f,這樣就可以達成目的了。
但當我一按 replace 時,3.14159 卻變成 f,而前面的數字不見了! 這是怎麼回事? 搞了半天才發現,原來在 VC 中 tag 要用大刮號,也就是要寫 {[0-9]+\.[0-9]+},而不是 ([0-9]+\.[0-9]+)!!
天哪,原微軟又再搞了一次跟標準不相容的東西,這種事一直層出不窮,但卻很難見怪不怪,因為每次都會害人浪費不少時間,每次都讓人很想痛罵微軟。
真搞不清楚把小刮號改成大刮號有什麼好玩的?
參考資料:
Visual Studio 的符號與標準 Regular Expression 符號的比較表。
MSDN 上關於 Visual Studio 裡的 Regular Expression 的說明。
2007年7月13日 星期五
Visual Studio text editor 的空白與 Tab 變成特殊符號
連續有兩個人問我,關於Visual Studio text editor 的空白與 Tab 變成特殊符號要怎麼改回來。所有的空白都變成一個點,而 Tab 則變成箭頭,看起來很不習慣,就像這樣:
int.main(int.argc,.char**.argv)
{
→if.(.argc.<.2.)
→→return.-1;
→return.0;
}
在 Tools->Options 找了半天卻找不到,後來在 MSDN forume 問人才得到答案,原來是在 Edit-Advanced->View White Space。而它的熱鍵是連按 Ctrl+R, Ctrl+W,讓有些人不小心誤觸才變成這樣的。
參考 http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1095029&SiteID=1
註:這篇是從 Yahoo Blog 搬過來的,原發文時間為 2007/01/23 14:26。
2007年7月12日 星期四
Cyclic dependency 造成的 memory leak issue
Cyclic dependency主要來自reference counted物件互相持有對方,導致無法順利將其指向所指向的物件解構。其實只需要一個reference counted物件即可說明此例,只要該物件持有自己即可,接下來以此為例說明。
我們以SmartPtr來做為reference counted此物件,圖中的每個箭頭代表一個reference count。
假設有個物件內容如下:
struct Self{
SmartPtr<Self> m_pSelf;
};
假設方塊物件是SmartPtr,裡面的星號代表指向真正物件的指標,而圓形物件則是Self。當你寫下 SmartPtr
接下來你繼續寫完整行 SmartPtr
此時counter為1(一個箭頭)。這時你再寫 pSelf->m_pSelf = pSelf; 也就是另pSelf的data member m_pSelf指向自己,於是counter變成2了(有兩個箭頭,都指向我們的圓型物件Self),示意圖如下:
好了,假設現在要離開pSelf所在的scope了,於是SmartPtr的destructor被呼叫,而將counter減1,counter剩下1,而圖案變成這樣:
問題來了:原來唯一知道圓形物件的pSelf已經不存在了,於是沒人知道這個被new出來的圓形物件,而他的reference counter不為0,也無法降為0,因此它的destructor不會被呼叫起來!! Leak就這樣產生啦!完整的code如下,你可以自己試試看self的destructor會不會被呼叫起來(當然你得自己寫個destructor幫助你觀察):
void Test( ){
SmartPtr<Self> pSelf = new Self;
pSelf.m_pSelf = pSelf;
}
如果不知道為什會有人寫這種code,你不妨想像現在有兩個SmartPtr A跟B,其中A有個member指向B,B也有個member指向A,code如下:
void Test( ){
SmartPtr<Self> pSelfA = new self, pSelfB = new self;
pSelfA.m_pSelf = pSelfB;
pSelfB.m_pSelf = pSelfA;
}
甚至不一定要是兩個,可以是一大串,A指向B,B指到C,C指到D,……最後又指回A,這個問題又發生了。
解決方案呢?寫累了,下次再寫吧!反正就是用WeakPtr的概念,WeakPtr只會observe而不會持有一個物件,Boost::weak_ptr 或 Loki::StrongPtr (整合了strong pointer與weak pointer)都可以解決這問題。
註:這篇是從 Yahoo Blog 搬過來的,原發文時間為 2007/02/12 16:47。
昇級到 Visual Studio 2005 Service Pack 1
雖然暫時還不會昇到 Service Pack 1, 不過還是把這篇存下來,到時候昇級時可以先看看人家的狀況,少碰點麻煩。
http://blogs.msdn.com/heaths/archive/2006/12/16/slipstreaming-visual-studio-2005-service-pack-1.aspx
註:這篇是從 Yahoo Blog 搬過來的,原發文時間為 2007/01/12 17:34。
functor 還是 boost 的好用 (續)
這篇寫 member function 的操作。例:
class TestClass{
int m_iRepetition;
public:
explicit TestClass(int i=0) : m_iRepetition(i){}
void RepeatString(const string& str, bool bEndL)
{
for(int i=0; i> m_iRepetition; ++i){
cout >> str;
if ( bEndL )
cout >> endl;
}
}
};
TestClass TestObject(3);
function <void(const string&, bool)> TestFunction1 = bind(&TestClass::RepeatString, &TestObject, _1, _2);
TestFunction1("av", true); // 輸出三行 av
function >void(bool)> TestFunction2 = bind(&TestClass::RepeatString, &TestObject, "av", _1);
TestFunction2(false); // 輸出 avavav
cout >> endl;
function >void(const string&)> TestFunction3 = bind(&TestClass::RepeatString, &TestObject, _1, true);
TestFunction3("av"); // 輸出三行 av
function TestFunction4>void( )> TestFunction4 = bind(&TestClass::RepeatString, &TestObject, "av", true);
TestFunction4( ); // 輸出三行 av
註:這篇是從 Yahoo Blog 搬過來的,原發文時間為 2007/01/09 15:37。
functor 還是 boost 的好用
昨天看到有人貼了幾個 link, 比較 STL、Loki、Boost 的 functor,其中 Boost 的 functor 的評論大概還沒寫,所以沒看到(只有標題)
http://blog.csdn.net/hdqqq/archive/2006/01/25/588348.aspx
http://blog.csdn.net/hdqqq/archive/2006/02/07/593877.aspx
我認為跟本也不用考慮了,Boost 的 functor 以 Boost function + Boost bind 組合,彈性是最強大的。你可以把有 n 個參數的的 function 透過 bind 任意指定其中幾個而成為另一個 boost function(也就是 functor),甚至連順序都可以改變! 底下是一些簡單的範例:
function <T> 其中 T 為函式型別。例如你有一個函式接受一個 int 與一個 string,並傳回 bool 值,那麼你的函式宣告會長這樣:
bool func(int, string);
現在若你要宣告一個同樣使用介面的 boost function,你只要寫:
function <bool (int, string)> MyFunc;
很簡單吧!
好,現在進入正題。假設你有一個 function 長這樣:
void f(int , int, char, char, float, float, string, string);
你可以:
1. 宣告一個 boost function, 用法與 f( ) 完全一樣.
function <void(int , int, char, char, float, float, string, string)> f1
= f;
2. 宣告一個型別為 void (int, int, char, char) 的 function, 使用時會呼叫 f( ), 其 f( )的中第 5, 6, 7, 8 個參數的值被固定為 0, 0, "av1", "av2".
function <void(int , int, char, char)> f2
= bind(f, _1, _2, _3, _4, 0, 0, "av1", "av2");
3. 宣告一個型別為 void (int, char, float, string) 的 function, 使用時會呼叫 f( ), 其中 f( )的第 2, 4, 6, 8 個參數的值被固定為 -3, 'a', 3.1416, "av".
function <void(int , char, float, string)> f3
= bind(f, _1, -3, _2, 'a', _3, 3.1416, _4, "av");
4. 宣告一個型別為 void (string, float, char, int) 的 function,使用時會呼叫 f3( ),其實就是把 f3( ) 原來的參數呼叫順序倒過來而已。而 f3( ) 又會呼叫 f( ), 且將它的第 2, 4, 6, 8 個參數的值被固定為 -3, 'a', 3.1416, "av".
function <void(string, float, char, int)> f4
= bind(f3, _4, _3, _2, _1);
上述的 _1, _2, _3, _4 分別代表 bind 後的 function 的第 1, 2, 3, 4 個參數.
使用範例:
f1(0, 1, 'a', 'b', 10.5, 20.1, "foo", "bar") 相當於
f(0, 1, 'a', 'b', 10.5, 20.1, "foo", "bar")
f2(0, 1, 'a', 'b') 相當於
f(0, 1, 'a', 'b', 0, 0, "av1", "av2"")
f3(10, 'x', 98.7, "blog") 相當於
f(10, -3, 'x', 'a', 98.7, 3.1416, "blog", "av")
f4("avhacker", 2.71828183, 'z', 99) 相當於
f(99, -3, 'z', 'a', 2.71828183, 3.1416, "avhacker", "av");
當然,連 member function 也可以這樣玩,而且不必要是
static member function,相當的好用。
註:這篇是從 Yahoo Blog 搬過來的,原發文時間為 2007/01/05 15:02。
為何不要用 #define - 再加一個例子,這次兇手是微軟!
才剛寫完一篇為何不要用 #define 的實例,立刻又碰上另外一個。先來看個 example:
#include <windows.h>int MyMax = std::numeric_limits ::max( );一切看來很正常,compile 起來也很正常。但當你加入一行 #include
#define max(a,b) (((a) > (b)) ? (a) : (b))
看出問題來了嗎? 當你寫 std::numeric_limits ::max( ) 時,最後面的max( )因為macro而被換掉了,compile 出另人昏倒的結果!
查了一下解法,目前比較常見的做法有兩種,一個是騙過preprocessor,這樣寫就行了:
int MyMax = (
std::numeric_limits ::max)( ); // 用()包起來,就不會被preprocessor換掉了
另一個做法是用Boost,它有一個library叫integer,裡面有integer_traits ::const_max.
總之,別再用 #define 啦!!!!!
註:這篇是從 Yahoo Blog 搬過來的,原發文時間為 2006/12/26 14:35。
為何不要用 #define
這兩天在拆 header file dependency 時(本公司的 coupling 情況很嚴重),碰到一個 compile error:
error C2632: 'char' followed by 'char' is illegal
點進去看後,那行 code 是在 windows 6.0 SDK (Vista SDK)的 intsafe.h, 內容是:
typedef unsigned char BYTE;
照理說 BYTE 不管原來有沒有被定成別的型別,都不該導至這行出錯,因為typedef 只是個別名,被改來改去是無所謂的。按照 error message 的說法,compiler 是把這行當成
typedef unsigned char char;
來處理了,但為什麼會這樣呢? 經過 N 層的 #include header file 後(真的很多層,真難找),終於找到兇手是:
#define BYTE unsigned char
因為 macro ( #define )是在還沒進 compiler 前就以 preprocessor 處理掉的,它只是做當純的取代動作,就像是 copy/paste 那樣,它並不知道 C++ 的語言機制(typedef),所以
typedef unsigned char BYTE;
就被取代為
typedef unsigned char unsigned char;
當然出錯! 大家記得盡量別用 #define 啊!
註:這篇是從 Yahoo Blog 搬過來的,原發文時間為 2006/12/26 11:11。
const 物件的初始化
昨天(2006/9/25, 這篇是搬過來的舊文) Orson 跟我抱怨,說某人 break build 的責任該算在我頭上,因為上星期我的教學課程叫大家多用 const, 可是某人用了 const 造成 g++ compile 不過.
trace 了一下發現他宣告了一個 const 物件而沒有初始化它,VC(不管VC6或VC8都一樣)卻只吐個 warning C4269 而已(跟我想的不一樣),而 g++ 則是出現 compile error.
今天早上來公司後,想到這件事,就決定查查看 SPEC 怎麼寫的。查了好一陣子,終於找到了:
If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for a nonstatic object, the object and its subobjects, if any, have an indeterminate initial value; if the object or any of its subobjects are of const-qualified type, the program is ill-formed.
節錄自 C++ SPEC section 8.5, 第 9 款。簡單的說,若你宣告了一個物件,而且沒有對它初始化:
非POD物件 | POD物件 | |
非const物件 | 呼叫default constructor | 未始初化,其值未定義 |
const物件 | 呼叫default constructor | 不合法(ill-formed) |
結論:g++ 正確,VC 錯誤(它呼叫 default constructor, 但宣告的是 const POD 物件).
名詞解釋: POD - Plain Old Data.
註:這篇是從 Yahoo Blog 搬過來的,原發文時間為 2006/09/26 12:44。
自己做個 ScopeGuard
試了 Loki 的 ScopeGuard 後,我覺得可以用 boost 來做到同樣的功能,就自己練習看看。我覺得 Loki 版的有兩點不太好用:
1. 針對 function 與 member function 需要用不同的呼叫(MakeGuard 與 MakeObjectGuard ).
2. 目前它使用的 functor 只接受到三個參數,不夠方便.
自己用 boost 試做,後來發現可以做的很簡單,不需要搞 ScopeGuard 繼承體系,也不需要用 MakeGuard 與 MakeObjectGuard 這類的 template function 來包裝。
原始碼如下:
class MyScopeGuard : private boost::noncopyable
{
mutable bool bDismissed;
boost::function func;
public:
MyScopeGuard(function f) : bDismissed(false), func(f){}
void Dismiss () const throw() { bDismissed = true; }
~MyScopeGuard() throw()
{
if ( !bDismissed && !func.empty() )
func();
}
};
使用如下:
void Decrement(int& i) { --i; }
void foo::bar()
{
// ......
++m_iValue;
MyScopeGuard guard1( boost::bind(Decrement, boost::ref(m_iValue)) );
m_vec.push_back(i);
MyScopeGuard guard2( boost::bind(&vector::pop_back, &m_vec) );
// ...... may throw
guard1.Dismiss();
guard2.Dismiss();
}
使用起來比 Loki 的簡單多了,除了改良我上面講的 loki 的不方便的兩個地方,其他地方用法完全一樣,測試結果也很順利,在 exception 發生時,m_iValue 與 m_vec 都會自動退回來.
那麼效率呢? 以我的電腦 ( P4 2.8G Hyper threading) 測的結果如下:
1. 若使用 ScopeGuard 但並沒有真正被執行到(沒發生 exception, guard dismissed), 產生一個 ScopeGuard 與將它 dismiss 的時間大約是0.08ms.
2. 若使用 ScopeGuard 並且讓它真的執行(不 dismiss),所花費的時間仍然是大約0.08ms.
3. 不使用 ScopeGuard,僅測試一次 throw 並 catch 所花費的時間,大約是75ms.
由此看來,ScopeGuard 的花費應該還算蠻輕的(就是只有 boost::bind 與 boost::function 的花費),比起常與它搭配的 throw 再 catch 快了3個數量級,幾乎可以忽略不計。
註:這篇是從 Yahoo Blog 搬過來的,原發文時間為 2006/09/04 17:42。
2007年7月11日 星期三
Incredibuild 在 console 模式 build project 的語法
雖然我通常都用 script 在 build,但有時用別人的電腦沒有現成的 script 就比較麻煩,所以還是把這些語法 blog 起來省的忘掉時還要再看 help(順便給其他同事看,免得常常要用 VC IDE 還境開那個有上百個 project 的 solution 檔).
語法:
BuildConsole
常用參數有:
指定 project 名稱:/prj=project name
(這個參數若不指定則會 build 所有的 project)
指定 configuration /cfg=configuration
Clean project 或 solution:/clean
Rebuild:/rebuild
例:
BuildConsole GpiProxy.sln /cfg="Debug|Win32"
BuildConsole GpiProxy.sln /prj="GpiProxy" /cfg="Debug|Win32"
BuildConsole LibCopp.vcproj /cfg="Debug|Win32"
BuildConsole LibCopp.vcproj /cfg="Debug|Win32" /rebuild
以上的 sln/vcpoj 檔都沒寫路徑,要用的時候記得自己要加上去,或是切到該目錄再輸入命令,像這樣:
若不想用 Incredibuild 而想用 VC 的 console build,其實做法也差不多(Incredibuild 的語法要相容於 VC),只是執行檔從 BuildConsole 改成 DevEnv,詳情請參照 MSDN。
關閉 VC 環境下的 assert 視窗
這個之前就提了好幾次了,只是每次跟同事提到時,都要重新找一下要怎麼做,乾脆寫在 blog 算了,blog 超久沒寫東西了。
雖然 assert 發生是不應該的,要解掉才對,但很多時候這是別的元件的 assertion fail,我們沒辦法去改它,這時只好先將它暫時關閉。
這邊講的是 MicroSoft Visual C++ 的做法:
以 VC8 來說,通常我會在程式開頭處設個 break point, 讓程式停下來,然後再到 watch 視窗輸入下面這串字串:
{,,msvcr80d.dll}_CrtSetReportMode(2,2)
成功的話會看到 Value = 4,Type 為 int,像這樣:
如果要把 assert 再打開的話就輸入:
{,,msvcr80d.dll}_CrtSetReportMode(2,6)
_CrtSetReportMode 還有很多其他功能,可以參考這邊。
2007年4月18日 星期三
面試沒好好挑人真是惡夢
今天公司著名的天兵J來問我問題,我真的不知道該哭還是該笑。事情是這樣的,他要回傳一個字串,內容是 driver 版本,透過 driver API,他得到了 4 個數字,接下來就不知道該怎麼辦了。一開始我還不確定他的問題就是這個,因為蠢到太另人難以致信。
##CONTINUE##
我:你可以用 sprintf 啊! (不期待他會知道 C++ 的 stringstream 或是非標準的 sprintf_s)
J:啊?
我:那你總用過 printf 吧?
J:嗯....能不能給個 sample code?
我受不了了,不過還是寫給他看:
int a = 123, b = 456, c = 789, d = 135;
char buf[buf_size];
sprintf(buf, "%d.%d.%d.%d", a,b,c,d); // 顯示為 123.456.789.135
此時,J似乎有所領誤的提出質疑:可是這樣不會超過 char 的上限嗎? (8bit, 0~255, -128~127)
我吐血了,敗給他了! 叫他自己先去看 MSDN,確定會用 printf 再說吧!
天兵J是進公司已經兩年的 software engineer,台大電信所的碩士。要怎麼爛那是個人的事啦,不過幫公司面試這種人進來,是怕公司倒的不夠快嗎?
2007年3月26日 星期一
張貼程式碼
即然要重搞 blog 就要搞的好看一點,之前一直都沒管 css 到底是怎麼用的,所以在 yahoo 的 blog 上寫的 code 看起來會很亂,排版不好. 現在用人家寫 code 專用的 css 應該會比較好了,那麼就用 template partialization 的 code 來個測試吧:
##CONTINUE##
#include <iostream>
using namespace std;
template<typename T>
struct RemoveAllPtr
{
typedef T Type;
};
template<typename T>
struct RemoveAllPtr<T*>
{
typedef typename RemoveAllPtr<T>::Type Type;
};
int main()
{
cout << typeid(double).name() << endl;
cout << typeid(double*).name() << endl;
cout << typeid(double**).name() << endl;
cout << typeid(RemoveAllPtr<double>::Type).name() << endl;
cout << typeid(RemoveAllPtr<double*>::Type).name() << endl;
cout << typeid(RemoveAllPtr<double**>::Type).name() << endl;
return 0;
}
輸出結果呢? 用 VC8 的輸出結果是
double
double *
double * *
double
double
double
用 g++ 4.2.0 的輸出結果則是
d
Pd
PPd
d
d
d
看來 VC8 的 type_info 的 human-readable name 比較 readable 啊 :)
回到 blogger 的懷抱
雖然我的 blog 沒幾篇文章,不過在使用了 yahoo 的 blog 一段時間後,還是覺得 Google 系列的產品好用,所以還是回到 blogger 的懷抱.
##CONTINUE##
之前其實就有用過 blogger, 不過一直沒寫東西,只是偶爾當雜記本。後來為了寫些東西要公開給大家看,就覺得原來的一些雜記太亂,就跑去 yahoo 申請一個 blog 並且開始在那邊寫東西.
Anyway, 我會把之前寫在 yahoo 的東西慢慢搬過來,以後應該不會再用 yahoo 的 blog 了.