發表文章

目前顯示的是 四月, 2013的文章

用 mutt 作為 command line 寄信程式

預設的 mail 不方便夾帶附加檔, 備忘一下用 mutt 做這事的指令:mutt -s TITLE EMAIL -a ATTACHMENT < CONTENT

python BaseHTTPServer 速度緩慢的原因

在用 Bottle 的開發模式時, 發覺有時候速度會異常的慢。等到受不了以後, 按下 ctrl+c 看到以下的 backtrace:Exception happened during processing of request from ('xxx.xxx.xxx.xxx', 37515) Traceback (most recent call last): File "/usr/lib/python2.7/SocketServer.py", line 284, in _handle_request_noblock self.process_request(request, client_address) File "/usr/lib/python2.7/SocketServer.py", line 310, in process_request self.finish_request(request, client_address) File "/usr/lib/python2.7/SocketServer.py", line 323, in finish_request self.RequestHandlerClass(request, client_address, self) File "/usr/lib/python2.7/SocketServer.py", line 638, in __init__ self.handle() File "/usr/lib/python2.7/wsgiref/simple_server.py", line 121, in handle self.rfile, self.wfile, self.get_stderr(), self.get_environ() File "/usr/lib/python2.7/wsgiref/simple_server.py", line 85, in get_environ host = self.address_string() File "/usr/lib/python2.7/BaseHTTPServer.py", line 49…

C++ 執行後掛在 __cxa_pure_virtual

今天遇到一個神奇的 bug, 程式掛掉後, 從 backtrace 看到其中一個函式名稱為 __cxa_pure_virtual, 從字面上的意思來看, 我呼叫了一個 pure virtual function, 所以程式掛了。但是 compiler 應該能抓到在 C++ 內呼叫 pure virtual function (Btw, Objective C++ 則否), 沒道理在 runtime 遇到這情況。 google 了一陣子, 看到這篇說有可能是呼叫 dangling pointer 的 virtual function, "Pure Virtual Function Called": An Explanation 則解釋各種可能的觸發原因。最後抓到兇手, 確實是呼叫 dangling pointer 的 virtual function。 依文章的解釋, destructor 會改變 virtual method table pointer 指向的位置, 最後會指向 abstract base class 的 virtual table, 裡面的 virtual function 則指向某個表示 pure virtual function 的指標 (gcc 用__cxa_pure_virtual)。所以, 若刪除指標後剛好記憶體內容保持原樣, 執行後就會呼叫到 __cxa_pure_virtual。 依管理記憶體的方式, 刪除指標時可能會保留原狀, 也可能填入特殊值故意觸發 crash。呼叫 dangling 可能會有不同結果。

在 linux 和 iOS 上抓 memory leak 和 heap profiling 心得

問題描述首先要定義一下什麼是「memory leak」。它的正式定義是指「程式弄丟了未釋放空間的位置」, 之後無法使用這塊空間也無法釋放它。另一方面, 程式沒有弄丟位置, 但是配置的空間愈用愈大, 或是用完後沒有歸還, 導致記憶體不足。若要應付第一種情況, 可用 memory leak 作為關鍵字找相關討論; 第二種情況要用 memory profiler 或 heap profiler 了解記憶體用去那裡, ( 感謝 Scott 告知 )。 就我自己少量的經驗來說, 第二種比較棘手, 第一種通常是粗心, 找到後補上 free/delete 即可。但第二種可能和程式配置和運用記憶體的策略有關。我遇到的問題都是第二種。若程式有針對不同區塊自己管記憶體的話, 比較方便日後植入統計程式找出瓶頸。順道一提, 如同 TDD 的精神, 在設計程式架構時就考慮測試, 會讓程式更易測試、維護和除錯。在設計架構時就考慮除錯, 也會讓程式更易維護和除錯。 在 Linux 上找 memory leak 和 profile heap在 Linux 上試了兩套工具 mtracevalgrind。mtrace 滿簡單的, 可用來抓 C 的 memory leak, 但不適用於 C++, 原因是 mtrace 在 malloc/free 動手腳, 可以找出那一行呼叫 malloc 後沒呼叫 free。但是 C++ 的情況是 libstdc++ 呼叫 malloc, 而我們有興趣的是誰呼叫了 new。 後來改試 valgrind 效果還不錯。valgrind 是多個除錯工具的集合體, 我試了兩個工具: memcheck: 抓 memory leak 和記憶體讀寫錯誤。 massif: profile heap 的用量, 可看到不同時間 heap 由各函式配置的比例。使用 valgrind 的代價是程式會慢個 20 倍左右。但是用工具協助檢測問題, 99% 的情況會比自己憑空猜想來得準。還是有些耐性使用 valgrind 會比較快找到問題源頭。memcheck$ valgrind --tool=memcheck --leak-check=full PROG PROG_ARG ... 跑完後會輸出結果在 console。建議先有些耐心看完官網文件。對 memcheck 的報表有疑問的話…