搜尋此網誌

2015年3月19日 星期四

How to use auto_ptr to avoid memory leak

Memory leak一直是程式debug的其中一項難題。
在C++中一項常見的錯誤就是new之後忘了delete,而導致此記憶體沒被回收重新使用。

Example:

void test()
{
    int* ptr = new int[5];
    // 一些操作後
}

void main()
{
    test();
}

上述的例子,是在說明當你使用function member或者function call去操作new出來的記憶體,卻忘了在程式最後去delete掉,將記憶體還回去,而此pointer在function結束後也沒辦法操作了,因此就造成了memory leak。

依照C++98的定義裡面介紹了auto_ptr就是用來解決此問題。
使用方式很簡單如下

auto_ptr<T> test(new T); //其中T代表任何資料型別
因此當test 的生命週期結束的時候,自然test會被回收使用

然而 auto_ptr有幾項缺點
1. auto_ptr當作參數傳給function時,在function結束後記憶體會被回收,原本的記憶體在主程式上就沒辦法被使用了。
2. auto_ptr不能使用在array,會有runtime error
3. auto_ptr不能使用在標準容器如vector, list, map...等等

Example1: 會在main()裡面的cout 出現crash,因為記憶體已經在Fun這個function結束被回收。
//***************************************************************
class Test
{
public:
 Test(int a = 0 ) : m_a(a)
 {
 }
 ~Test( )
 {
  cout<<"Calling destructor"<<endl;
 }
public:
 int m_a;
};
 
 
//***************************************************************
void Fun(auto_ptr<Test> p1 )
{
 cout<<p1->m_a<<endl;
}
//***************************************************************
void main( )
{
 std::auto_ptr<Test> p( new Test(5) ); 
 Fun(p);
 cout<<p->m_a<<endl;
} 

2015年3月8日 星期日

Template 樣板

樣板分成以下幾種
1. 樣板函式
2. 樣板類別
3. 函式樣板
4. 類別樣板

其中第一和二的達成則是靠重載(overload)來實現,而三跟四則是透過template的宣告來達成。

而這其中的差異性就是 樣板函式或樣板類別在overload時已宣告成已知的資料型別。
函式樣板跟類別樣板則是可以使用任何資料型別來實現。
Notice: 函式樣板跟類別樣板因為可以使用任何資料型別,所以記憶體使用上較多。

函式樣板跟類別樣板的使用時機為:對於任何的資料型別都是使用相同的操作
使用樣板的好處是對於不同資料型別不需要再overload多次。

函式樣板宣告方法有三種
1. template < class T >
2. tempate < typename ElementType >
3. template< class BorderType, class FillType >

Example:
template< class T > // 宣告此function為樣板
void printArray( const T *array, const int count) // 其中T代表任意的資料型別

也可為如此
template< class T, int count>
void printArray(const T *array)

使用方式
int a[5] = {1,2,3,4,5};
printArray(a, 5); //代表array為int的資料型態

char b[] = "Hello";
printArray(b, sizeof(b)); //代表array為char的資料型態


2015年3月4日 星期三

How to enable core dump in Android

什麼是core dump?
簡單來說就是可以幫助你快速debug的工具,wiki上有比較詳細的解釋
http://en.wikipedia.org/wiki/Core_dump

如何確認系統有無啟動core dump?
透過 ulimit -c 如果返回 0代表沒有啟動core dump

如何啟動?
設定ulimit -c ulimited即可

產生的core dump在哪裡?
例如: Test 程式放在/usr/local/bin下面,則產生的core dump就在同樣目錄下且預設名字叫core的檔案。
如果要修改coredump存放的位置,可以修改/proc/sys/kernel/core_pattern
例如: echo /data/core > /proc/sys/kernel/core_pattern

以上是程式直接執行所產生出來的,如果要透過Android的話則需要另外的方式
如果你的程式是透過 Android的 init程式帶起來的
例如:
service dtvloaderserver /system/bin/dtvloaderserver
            class main
            user root

則你另外需要設定以下的方式在init.rc裡面
加上下面的修改
setrlimit 4 -1 -1
mkdir /data/core 0777 system system

write /proc/sys/kernel/core_pattern /data/core/%t-%e-%p-%c.core

%t -- dump時間 (1970年1月1日0:00開始算起的秒數)
%e -- 執行檔名
%p -- PID
%c -- dump大小上限

如何使用core dump來debug?
gdb -c xxx.core ./test

怎麼產生core dump? 以下是一個範例
int test(RpcClient& client)
{
    int *a = NULL;
    *a = 0x1; à透過存取位址0來產生coredump
    return 0;
}

執行./ClientTest -test 發生segmentation fault (core dumped) à代表產生core dump











怎麼使用coredump debug?
使用GDB可以馬上定位到錯誤的code 位址