2013年5月30日 星期四

linux thread 與 signal

雖然是基礎知識, 一陣子沒用大概會忘記, 備忘一下重點:

  • 在 multi-thread 情況下, signal() 的行為是未定義, 必須用 sigaction() 註冊 signal
  • 用 kill 送 signal 給 process 後, process 內任何一個 thread 都有可能執行 signal handler。若不希望特定的 thread 收到 signal, 可用 pthread_sigmask() 改變特定 thread 的行為, 或是用 pthread_kill() 送出 signal 給指定的 thread
  • SIGSEGV 會送給發生 segmentation fault 的 thread。所以有 core dump 的時候, gdb 可以正確找出那個 thread 造成 segfault

參考資料:

和 Ubuntu 安裝套件相關的知識

先散亂地記在這邊, 慢慢補完:

1. 用 apt-get cache FILE 從檔案反查套件名稱

2. http://packages.ubuntu.com/ 找詢是否有這套件, 那一版開始有這套件 (Distribution 選 "any")

3. 套件分類 ( 參考資料 )

  • main: Free software, officially supported by Canonical
  • universe: Free software, NOT supported by Canonical
  • restricted: Non-free software officially supported by Canonical
  • multiverse: Non-free software NOT supported by Canonical

X 版本 (如 X = precise) 的 X-updates 表示 stable release update, 會有比較新一點的套件。預設 /etc/apt/sources.list 裡應該已有 X/X-updates 和 main/universe/restricted/multiverse 組合的八種來源。

4. 用 apt-cache policy PKG 了解安裝的優先順序

例如:

$ apt-cache policy sqlite3
sqlite3:
  Installed: 3.7.9-2ubuntu1.1
  Candidate: 3.7.9-2ubuntu1.1
  Version table:
 *** 3.7.9-2ubuntu1.1 0
        500 http://free.nchc.org.tw/ubuntu/ precise-updates/main amd64 Packages
        100 /var/lib/dpkg/status
     3.7.9-2ubuntu1 0
        500 http://free.nchc.org.tw/ubuntu/ precise/main amd64 Packages

使用 vim script 自動開啟 C/C++ 程式的標頭檔或程式碼

先附上完整 script:

" Open .h if it's a cpp file, and vice versa.
function! OpenComplementFile()
  let f = expand('%')   " (1)
  let suffix = matchstr(f, '\.\a\+$')
  let pattern = suffix . "$"
  if suffix == '.h'
    let suffixes = ['.cpp', '.cc', '.mm', '.m', '.h']
    for suf in suffixes
      let target = substitute(f, pattern, suf, '')   " (2)
      if filereadable(target)
        break
      endif
    endfor
  elseif suffix == '.cpp' || suffix == '.cc' || suffix == '.m' || suffix == '.mm'
    let target = substitute(f, pattern, '.h', '')
    if !filereadable(target)
      let tmp = target
      let target = substitute(tmp, '\v(.+)\..+', 'public/\1.h', '')  " (3)
      if !filereadable(target)
        let target = substitute(tmp, '\v(.+)/(.+)\.(.+)', '\1/public/\2.h', '')
      endif
    endif
  else
    let target = ''
  endif

  if filereadable(target)
    exec 'vsplit ' target
  else
    echo "Complement file not found"
  endif
endfunction
nnoremap <silent> <F4> :call OpenComplementFile()<CR>

在 vimrc 裡放入上述程式, 然後在 normal mode 裡按 F4 會有如下的反應:

  • 若是在 X.h 裡面, 會試著在垂直分開的視窗裡開啟 X.cpp, 若沒有 X.cpp, 則會依序改試 X.cc, X.mm, X.m。
  • 若是在 X.cpp (或 .cc, .mm, .m) 裡, 會先試開 X.h, 若沒有 X.h, 再試 public/X.h。有需要的話, 可以配合自己的習慣往更深的目錄找。

1.

  • 詳見 :h expand。
  • % 表示目前的檔名。
  • 簡單的檔名轉換可以用 expand 就做完, 比方說如下的例子:
"open A_test.X if current file name is A.X
"open A.X if current file name is A_test.X
function OpenCorrespondingFile()
    let d = split(expand("%"), '_test')
    if len(d) == 1
        let name = expand("%:r") . "_test." . expand("%:e")
    else
        let name = d[0] . d[1]
    endif
    exec 'vsplit ' name
endfunction

2.

  • 寫上述 script 的時候, 花最多時間查詢如何使用函式 substitue()。參考 vim 內部的說明 :h substitute() 即可。
  • 注意要加 () 表示查詢函式的文件, 而不是查 Ex command 的 :substitute

3.

  • :h magic 說明 vim 對待特殊字元的方法。在 pattern 前面加上 "\v" 會和其它 script 的用法一致, 比較方便。

2013年5月3日 星期五

使用 --start-group 和 --end-group 解決 circular dependencies

只是想備忘這篇: GCC: --start-group and --end-group command line options - Stack Overflow

關鍵的 gcc 指令:

-Wl,--start-group -lmy_lib -lyour_lib -lhis_lib -Wl,--end-group -ltheir_lib
  • gcc man page 說明 -Wl,X 傳遞參數 X 給 linker
  • ld man page 說明 --start-group archives --end-group

這個作法的好處是不用理會 static library 在參數裡的順序 (預設是假設 A 依賴 B 時, A 要放在 B 前面), 壞處是會加長 linking 時間。

Btw, 遇到和 linking 相關的問題時, 記得要同時從 compiler 和 linker 的角度看問題。

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...