這篇只是介紹比較知名的方法,預計之後還會再發一兩篇討論 C++/Qt 的回收手法。
TAG
首都機能移轉
(2)
歌詞
(2)
靠北文
(40)
戲言
(30)
糟糕
(7)
ACG
(23)
Assembly
(2)
Boost
(2)
C
(31)
C++
(69)
CMake
(4)
CSIE
(67)
Debian
(34)
Design_Pattern
(2)
Django
(1)
Eclipse
(1)
en_US
(13)
FFmpeg
(3)
FoolproofProject
(26)
FreeBSD
(2)
Git
(4)
GNU_Linux
(65)
IDE
(5)
Java
(11)
JavaScript
(19)
KDE
(15)
Khopper
(16)
KomiX
(3)
Kubuntu
(18)
Life
(1)
Lighttpd
(2)
Mac_OS_X
(2)
Opera
(1)
PHP
(2)
PicKing
(2)
Programing
(21)
Prolog
(1)
Python
(7)
QSnapshot
(2)
Qt
(30)
Qt_Jambi
(1)
Regular_Expression
(1)
Shell_Script
(7)
Talk
(98)
VirtualBox
(7)
Visual_Studio
(13)
Windows
(18)
zh_TW
(36)
2012年7月15日 星期日
2012年5月12日 星期六
How to debug a program which grabs X11 input events
最近在做的抓圖程式, 因為要在非 focus 狀態也能接收到抓圖要求, 必須取得所有的輸入事件控制權.
但如果必須要在這種地方下中斷點, 因為 X11 所有的輸入都被搶走了, 你無法操作 gdb.
但如果必須要在這種地方下中斷點, 因為 X11 所有的輸入都被搶走了, 你無法操作 gdb.
類別:
C,
C++,
GNU_Linux,
Programing,
zh_TW
2010年11月25日 星期四
你永遠料不到自己有多蠢
最近某個作品在開啟檔案時會不定期當掉 ... 原本一直找不出原因, 直到我在除另一個不相關的 bug 時發現這個函式:
const char * fromURI( const QUrl & uri ) {
QByteArray tmp( uri.toString().toUtf8() );
#ifdef Q_OS_WIN
if( uri.scheme() == "file" ) {
tmp.prepend( 'w' );
}
#endif
return tmp;
}
類別:
C,
C++,
Programing
2010年4月2日 星期五
Converting literal
#include <stdio.h>
int main() {
for( char tmp[1024]; fgets( tmp, sizeof( tmp ), stdin ) != NULL; ) {
for( unsigned char * c = tmp; *c; ++c ) {
if( *c == '\n' ) {
printf( "\n" );
} else {
printf( "\\x%02X", *c );
}
}
}
return 0;
}
類別:
C,
CSIE,
Programing,
zh_TW
2010年3月14日 星期日
Using UTF-8 literals in source code
直接在 code 裡打 UTF-8 字元在有的 IDE 會無法辨識,像是 Visual C++ 2005 和 2008 堅持使用 locale 的編碼來解讀 source,導致換 locale 就會編譯失敗。
這種時候沒什麼有效的解決方法,就是用 hex escape 字元啦 ...
這種時候沒什麼有效的解決方法,就是用 hex escape 字元啦 ...
/* 正體中文 in UTF-8 */ const char * utf8 = "\xE6\xAD\xA3\xE9\xAB\x94\xE4\xB8\xAD\xE6\x96\x87";很煩,很難讀,不過至少所有的字元都保證在 C / C++ 的標準字元集裡;只是最好在旁加上註解說明那應該是什麼字,否則很難維護。
類別:
C,
C++,
CSIE,
Programing,
zh_TW
2010年2月13日 星期六
Multiple processes building with Visual C++
MinGW32 的 make 好像還沒實作 --jobs 的功能 ... 反正各平台都有很多狗屁倒灶的鳥事啦。
類別:
C,
C++,
CSIE,
IDE,
Programing,
Visual_Studio,
Windows,
zh_TW
2009年11月29日 星期日
Array IS NOT pointer
呣,其實我大一的時候也有這種觀念,畢竟那時 pointer 還是個陌生的怪物,那還是個「如果你不會傳 array 就宣告成 global」的時代。
基本上 C 的 array 實在不怎麼討喜,包括它的「陣列大小一定要跟在陣列名稱後面」這種鳥語法,如果再加上 function pointer 那可真是醜斃了。之所以 array 經常和 pointer 混為一談,最大的原因應是 array 會被隱式轉型[?]為 pointer,且 array 變數本身的值就是 array 第一個元素的位址。這讓你可以把陣列丟入如下的函式裡:
基本上 C 的 array 實在不怎麼討喜,包括它的「陣列大小一定要跟在陣列名稱後面」這種鳥語法,如果再加上 function pointer 那可真是醜斃了。之所以 array 經常和 pointer 混為一談,最大的原因應是 array 會被隱式轉型[?]為 pointer,且 array 變數本身的值就是 array 第一個元素的位址。這讓你可以把陣列丟入如下的函式裡:
void f1( const int * array );呃,那二維陣列呢?
void f2( const int * * const array );因為並不存在多維陣列對 pointer 的隱式轉換,因此你無法直接丟進去。
接下來要談談 array 和 pointer 有什麼不同。
最顯著的性質是,array 變數本身是唯讀的,它無法再被賦值,其代表的空間也無法被手動釋放,而 pointer 值則可以變動,指向的內容可能可以被手動釋放;這也是 pointer 令新手感到易混淆的地方,因為它同時有資源的持有者以及迭代性質。
此外,pointer 可以被取址,但是 array 的址和它自己一樣,也就是陣列開始的第一個位址:
int cla[1]; printf( "%p %p\n", cla, &cla ); // the same
另一個較為有用的不同點是,array 可利用 sizeof 求大小,而 pointer 就只是個 pointer。
int8_t a[10]; sizeof( a ); // 10 int8_t * b = a; sizeof( b ); // 4 or 8, depends on your compiler那如果你很希望陣列在傳入函式後還是個陣列,C++ 的 template 可以幫得上忙:
template< typename T, std::size_t N >
std::size_t getByteLength( const T ( & array )[N] ) {
return sizeof( array );
}
// how to use:
int32_t tmp[4];
getByteLength( tmp ); // will return 16
坦白說,我不是很清楚為什麼一定要用 reference to array,不過你的確可以用這個 template function 傳 array。再多維也可以:
template< typename T, std::size_t N, std::size_t M >
std::size_t getByteLength2( const T ( & array )[N][M] ) {
return sizeof( array );
}
以此類推。2009年11月21日 星期六
2009年11月5日 星期四
A way to use C++ object in C callback
前幾天在用 libFLAC 的時候[?],它要求 client 註冊一個 callback 給它,prototype 長這樣:
可以看到最後一個
typedef FLAC__StreamDecoderWriteStatus (* FLAC__StreamDecoderWriteCallback) (const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data);看起來很複雜,其實不會,就是個 function pointer 的 typedef 而己[?]。
可以看到最後一個
void * client_data 是用來接受 client 的資料用的,先接 void * 再轉成自己要的型別,算是 C 的老手法了。
Well, 在 C++ 上使用時就沒有那麼簡單。第一個問題是 member function 需要實體才能使用。
簡單一個想法是宣告一個 struct,把實體和 pointer to member function 包起來,再傳給這個 callback function。不過一來這有點麻煩,二來你不能呼叫用 protected 或 private 修飾的 members。
沒關係,我們有 friend!
嗯,不好意思,這的確是可以動,不過真的很爛。
沒關係,我們有 friend!
嗯,不好意思,這的確是可以動,不過真的很爛。
還好我們還有另一顆子彈,就是 static member function。static member 不需要實體,且 member function 可以存取 class 內所有 member,這樣就一次解決了兩個問題。
所以我們的 callback 會長這樣:
不要譴責我沒用 dynamic_cast,我百分之百確定 client_data 是 FlacReader 好嗎?
所以我們的 callback 會長這樣:
static FLAC__StreamDecoderWriteStatus
FlacReader::writeCallback_
(const FLAC__StreamDecoder *decoder,
const FLAC__Frame *frame,
const FLAC__int32 *const buffer[],
void *client_data) {
FlacReader * self = static_cast< FlacReader * >( client_data );
// blah blah
}
client_data 那裡傳 this 就好。不要譴責我沒用 dynamic_cast,我百分之百確定 client_data 是 FlacReader 好嗎?
2009年9月18日 星期五
如何讓你的程式更難理解(5)
int uglystrieq( const char * l, const char * r ) {
while(*l&&*r&&(*l++|32)==(*r++|32));return *l--||*r--||(*l|32)!=(*r|32);
}
Compare the equivalence of two strings. Case insensitive.
[Edit]
This implementation while crash when passing a 0-lengthed string. Another version:
[Edit]
This implementation while crash when passing a 0-lengthed string. Another version:
int _(const char*l,const char*O) {
return ((*l|32)-(*O|32))?1:*l?_(l+1,O+1):0;
}
2009年8月1日 星期六
C++ 的多緒安全性
簡單的說,因為標準給編譯器優化的限度太寬鬆,導致編譯器可以很大程度地調換指令的順序,因此 critical section 也有可能無法完全包好。不少人以為 volatile 可以禁止優化,從而確保正確順序,但其實它只保證單緒的順序,多緒的狀況還是無法保證;連鬼才 Andrei Alexandrescu 都在他的神作 Morden C++ Design 裡犯了這個錯誤(我也不認為他示範的 Singleton 真的有 thread-safe)。
也許等 C++0x(呃,可能會變成 C++1X) 釋出之後,可以帶給我們更複雜的 C++ 吧。XD
也許等 C++0x(呃,可能會變成 C++1X) 釋出之後,可以帶給我們更複雜的 C++ 吧。XD
2009年5月2日 星期六
Compile C or C++ code from stdin
偶而你會懶得存檔,因此有方法可以直接編出來:
# for C
gcc -xc -
# for C++
g++ -xc++ -
# for example
echo 'main(){puts("Hello world!");}' | gcc -xc - && ./a.out
2009年4月15日 星期三
Export DLL symbols to LIB
用 gcc 如果要發佈成 dll,只要編譯器加點選項,就可以發佈給別人連結了。但是 Visual C++ 卻要在每個 symbol 上加上關鍵字 __declspec(dllexport) 才會匯出到 lib,然後才能連結。
__declspec(dllexport) void blah();
class __declspec(dllexport) Blah {};
不管怎麼說,微軟的確是這方面的天才。
類別:
C,
C++,
Visual_Studio,
Windows
2009年2月9日 星期一
該死
我實在不知道該怨恨誰了,就讓我恨天吧...(?)
故事的開頭,是在我想把程式port到Windows的時候發生的。
首先我遇到了TR1和C99名稱缺省的問題,沒關係,我知道每次都要跟上標準很累,VC沒有<cstdint>,gcc也沒實作std::tr1::regex,一人一次很公平,打平了,還好我還有Boost,不怕你。
然而沒想到魔王其實不在這裡,而是Unicode。
首先我遇到了TR1和C99名稱缺省的問題,沒關係,我知道每次都要跟上標準很累,VC沒有<cstdint>,gcc也沒實作std::tr1::regex,一人一次很公平,打平了,還好我還有Boost,不怕你。
然而沒想到魔王其實不在這裡,而是Unicode。
先簡單的介紹一下一般處理系統字串的方法好了。
大家都知道早期各國為了顯示自己的文字,定了各種了不起的編碼方式來對應字型,Big5的許功蓋就是這段歷史下的偉大人物,大概比踢牙齒老奶奶這位史詩級人物還要再個高一級左右。
夫天下大勢,分久必合合久必分,某個大有為的組織看不慣這種戰國亂象,於是制定了Unicode的編碼標準,以對應全人類的偉大文化產物,又生出了各種對應Unicode的編碼方式,希望能夠平息亂碼之亂。要注意的是,編碼標準和編碼方式不同,每個文字在Unicode裡只有一種編碼標準,再根據各種不同的編碼方式,比方說UTF-8或UTF-16,UCS4等編成不同的編碼。
大家都知道早期各國為了顯示自己的文字,定了各種了不起的編碼方式來對應字型,Big5的許功蓋就是這段歷史下的偉大人物,大概比踢牙齒老奶奶這位史詩級人物還要再個高一級左右。
夫天下大勢,分久必合合久必分,某個大有為的組織看不慣這種戰國亂象,於是制定了Unicode的編碼標準,以對應全人類的偉大文化產物,又生出了各種對應Unicode的編碼方式,希望能夠平息亂碼之亂。要注意的是,編碼標準和編碼方式不同,每個文字在Unicode裡只有一種編碼標準,再根據各種不同的編碼方式,比方說UTF-8或UTF-16,UCS4等編成不同的編碼。
那麼我們在程式裡是怎麼處理各種不同的輸入和輸出呢?
最常用的方法就是,把輸入字串解碼成Unicode字串,如此一來就可以在程式裡方便地處理字串,在輸出時再編碼成需要的輸出字串。
那要怎麼存Unicode字串呢?C和C++都提供了wchar_t來存寬字元,你可以用它來存放Unicode化過的字元。但是有趣的地方也在這裡,Windows和其他系統的wchar_t的寬度是不一樣的,Windows是2 bytes,Linux等是4 bytes,因此在Windows上你可能要選擇UTF-16,而在Linux上要用UCS4。
最常用的方法就是,把輸入字串解碼成Unicode字串,如此一來就可以在程式裡方便地處理字串,在輸出時再編碼成需要的輸出字串。
那要怎麼存Unicode字串呢?C和C++都提供了wchar_t來存寬字元,你可以用它來存放Unicode化過的字元。但是有趣的地方也在這裡,Windows和其他系統的wchar_t的寬度是不一樣的,Windows是2 bytes,Linux等是4 bytes,因此在Windows上你可能要選擇UTF-16,而在Linux上要用UCS4。
這還不是最糟糕的。
Linux的系統函式都沒有提供wchar_t的版本,因為現在系統上的編碼都是用UTF-8,就算用locale的編碼也不會漏失字元。
但是Windows就提供了另一套w開頭的API,以提供wchar_t的版本,同時系統函式分成兩系,一是W結尾,使用wchar_t,一是A結尾,使用char,而且要編成本地編碼。
Linux的系統函式都沒有提供wchar_t的版本,因為現在系統上的編碼都是用UTF-8,就算用locale的編碼也不會漏失字元。
但是Windows就提供了另一套w開頭的API,以提供wchar_t的版本,同時系統函式分成兩系,一是W結尾,使用wchar_t,一是A結尾,使用char,而且要編成本地編碼。
於是當某個你碰不到的程式碼內部使用fopen時,在Windows上你一點辦法都沒有,根本不能讀取non-ascii的路徑。
2008年11月19日 星期三
2008年8月18日 星期一
部置Visual C++程式
翻成"部署"還真是怪怪的....
我看就很麻煩,而且還失敗很多次....果然是DLL hell。
我看就很麻煩,而且還失敗很多次....果然是DLL hell。
類別:
C,
C++,
IDE,
Visual_Studio,
Windows
2008年7月31日 星期四
如何讓你的程式更難理解(3)
char * strcpy( char * dst, const char * src ) {
char * tmp = dst;
while( *dst++ = *src++ );
return tmp;
}
2008年7月23日 星期三
Self initialization
int i = i;這樣做gcc竟然沒問題....
再來看看C++的例子:
struct Test {
Test() : i_( 0 ) {
std::cout << "Default constructor" << std::endl;
}
Test( const Test & rhs ) : i_( rhs.i_ ) {
std::cout << "Copy constructor" << std::endl;
}
private:
int i_;
};
int main() {
Test a( a );
return 0;
}
可以看到只印出一個Copy contructor出來....而內部的變數是未定義的。
2008年5月28日 星期三
2008年3月31日 星期一
Debug Assembly Language With GDB
gcc -S blah.c # if you want generate from C as blah.s --gstabs -o blah.o # --gstabs enables debug flags gcc blah.o -o blah # link object file gdb blah # now you can debug it
訂閱:
文章 (Atom)