2013年3月21日 星期四

比 soft link 更好用的 mount --bind

當目錄 a 所在的 partition 沒空間但又得放東西在 a 下面時, 通常會另建 partition, 然後 soft link 新 partition 下某個目錄過來, 比方說從新 partition 用 soft link 指向 a/b。

這個作法有個缺點, 若 a/b/ 下的程式想透過 ../ 存取 a 目錄下的東西, 比方說用 ../c 取得 a/c。在 soft link 的情況會找不到 c, 因為 b 其實在另一個 partition, b/.. 並不是 a。

這時可用 mount --bind 解, 作法很簡單, 就直接抄 man mount 的內容過來備忘:

Since Linux 2.4.0 it is possible to remount part of the file hierarchy somewhere else. The call is
     mount --bind olddir newdir
or shortoption
     mount -B olddir newdir
or fstab entry is:
     /olddir /newdir none bind

和 C 前置處理器相關的小技巧

在 gdb 內查詢 macro

需要在編譯時加上 -g3, info macro 等指令才會有用。

參考資料: http://sourceware.org/gdb/onlinedocs/gdb/Macros.html

列出 include 的內容

$ gcc -E a.c

編譯錯誤指出缺少某個 symbol 時, 可用這招確定到底有沒有引入目標的宣告。有時 #ifdef 太多, 看原始碼不易確認這件事。

列出 define 的內容

比方說若想知道 errno 111 代表什麼意思, 可這麼做:
$ echo "#include <errno.h>" | gcc -dM -E - | grep " 111$"
#define ECONNREFUSED 111
再來 man errno 查詢 ECONNREFUSED 即可得到答案。
另外, 可用以下的方法得知系統預先 define 的東西
gcc -dM -E - < /dev/null
參考資料: http://stackoverflow.com/questions/2224334/gcc-dump-preprocessor-defines

2013年3月20日 星期三

python memory leak

由於 CPython 使用 reference counting 管理記憶體, reference count 到 0 時會立即釋放記憶體, 遇到 memory leak 時, 至少可以用 del 稍微自救一番。

import sys

a = []
print sys.getrefcount(a)  # 2
b = a
print sys.getrefcount(a)  # 3
del b
print sys.getrefcount(a)  # 2

如上所示, 可在程式中用 sys.getrefcount() 檢查 referece count 是否符合預期, 盡量在不用以後立即呼叫 del, 當 reference count 變為 0 時, 會提前釋放記憶體。

注意 python 的 while、for 沒有形成新的 scope, 有可能因此誤判一些物件的生命週期:

for i in range(10):
    pass
print i  # 9, 並非 NameError

備註

附上 CPython 2.7.3 Include/object.h 內關於減 reference 相關的程式:

769 #define Py_DECREF(op)                                   \
770     do {                                                \
771         if (_Py_DEC_REFTOTAL  _Py_REF_DEBUG_COMMA       \
772         --((PyObject*)(op))->ob_refcnt != 0)            \
773             _Py_CHECK_REFCNT(op)                        \
774         else                                            \
775         _Py_Dealloc((PyObject *)(op));                  \
776     } while (0)

可看出在 reference count 為 0 時, 確實會呼叫 deallocator。

今日休閒時間已用盡, 改天再來看看為什麼初始數值為 2。

2013年3月3日 星期日

Core Data lightweight migration

上份工作需要階段性處理大量資料, 當時有不少 database schema 與 data migration 的經驗, 雖然我不怎麼喜歡 Django 的 ORM, 不過配合 South 做 migration 到是滿方便的。

最近用 Core Data 不幸地在發佈測試程式後發覺需要增加欄位, 查了一下作法, 所幸 Core Data 有針對簡單的情況提供自動化 migration, 相當輕鬆, 簡記用法如下:

說明瀏覽器運作相關的文章

備忘一些不錯的概念文章:

  • WebKit for Developers - Paul Irish: 說明各家使用 WebKit 的瀏覽器到底共用的 WebKit 是什麼。另有附一份 slide 說明 "How WebKit Works", 不過 slide 講的內容就很少了。
  • How browsers work, 2011 年的文章, 說明瀏覽器運作的每個步驟

iOS delegation vs. notification

初始使用 iOS 的 NSNotificationCenter 覺得頗不錯的。UI 物件需要從一個遙遠的物件裡取得資料改變的狀態, 當初沒考慮好這個需求, 不太方便傳遞資料。這時用 notification 解套就容易多了。但是隱約覺得 notification 的用法不太妙, 查到這篇 When to use Delegation, Notification, or Observation in iOS 分析得很清楚, 摘要重點如下。
使用 notification 的缺點 (或說特色) 是:
  • notification 是非同步呼叫, 發送 notification 和接受 notification 在不同的 runloop iteration 裡, 不易除錯。
  • notification 的發送和註冊採用字串做為 key, 無法在編譯時期找到錯誤。執行時才會察覺「好像沒呼叫到」
另一方面, delegation 透過定義使用端的介面 (iOS 術語為 protocol), 運作的特點為:
  • 透過函式呼叫通知事件, 方便除錯
  • 可在編譯時期確保提供服務者和用戶端有正確串在一起
  • 除通知發生事件外, 可讓客戶提供實作供提供服務者使用
原文有提及更多項目, 不過對我來說最要緊的是「是否容易除錯」。從這個角度來看, 使用 delegation 遠比 notification 安全。所以可以的話, 盡量避免使用 notification 較好。

2013-03-03 更新

經 Sam 指正, 發覺 notification 預設是同步呼叫, 在 backtrace 裡可找到發出點和接收點。這樣就沒那麼難除錯了。重看一遍該篇文章, 作者提的除錯困難, 可能是指用太多 notification 混在一起的情況。

兩者的主要差別應該是介面的強度。介面規範強, 編譯時期自然抓到較多錯誤, 寫起來也比較麻煩一些。其它的小細節如「少了 observer 訊息、一對多 (多對一) 架構」等, 則是設計介面或使用時可補救的。

C++ 能否用 memcpy 複製 class / struct 的資料?

答案是: POD (plain old data) type 可以。POD type 可和 C 互通, CPP Reference POD Type 的介紹: Specifies that the type is POD (Plain Old Data) type. Thi...