跳到主要內容

發表文章

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. This means the type is compatible with the types used in the C programming language, can be manipulated using C library functions: it can be created with std::malloc, it can be copied with std::memmove, etc, and can be exchanged with C libraries directly, in its binary form. C++11 開始可用 std::is_pod 判斷在看 POD 定義的過程發現 Standard layout type 的定義也重要的: Specifies that a type is standard layout type. Standard layout types are useful for communicating with code written in other programming languages. 符合 standard layout type 才能用 reinterpret_cast 轉型成第一個 member 的 type 不過最穩的最法是直接用 C++11 提供的 std::is_trivially_copyable 判斷, 成立的話就可以安心地用 memcpy。
最近的文章

如何讓 C++ STL, smart pointer 和 forward declaration

有時在 class 內訂義 member 用 std::vector 或 std::unique_ptr, 可以用 forward declaration 宣告 MyObject, 有時不行。原因在於是否有觸發 compiler inline vector / unique_ptr 的 ctor / dtor。所以避免造成 inline ctor / dtor, 就可以用 forward declaration 宣告 MyObject, 降低程式之間不必要的 dependency, 減少重新編譯時間。 參考資料: Forward declaration with unique_ptr? The Chromium Projects: C++ Dos and Don'ts -> Stop inlining constructors and destructors

讀出 gcc/g++ 編譯的參數

這裡看來的,官方文件說 -grecord-gcc-switches 預設有開,所以滿可靠的。使用例子: $ g++ f.cpp -std=c++11 -g -o f $ readelf --debug-dump f | grep DW_AT_producer DW_AT_producer : (indirect string, offset: 0xded): \ GNU C++11 5.4.0 20160609 -mtune=generic -march=x86-64 -g -std=c++11 -fstack-protector-strong DW_AT_producer DW_FORM_strp 但用 clang 編的資訊就沒存完整: $ clang++ f.cpp -std=c++11 -g -o f $ readelf --debug-dump f | grep DW_AT_producer DW_AT_producer : \ (indirect string, offset: 0x0): clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final) DW_AT_producer DW_FORM_strp

(C/C++ ) 如何在 Linux 上使用自行編譯的第三方函式庫

以使用 LevelDB 為例。 抓好並編好相關檔案,編譯方式見第三方函式庫附的說明:$ ls include/ # header files leveldb/ $ ls out-shared/libleveldb.so* # shared library out-shared/libleveldb.so@ out-shared/libleveldb.so.1@ out-shared/libleveldb.so.1.20* 下面的例子用 clang++ 編譯,這裡用到的參數和 g++ 一樣。 問題一:找不到 header$ clang++ sample.cpp sample.cpp:5:10: fatal error: 'leveldb/db.h' file not found #include "leveldb/db.h" ^ 1 error generated. 解法:用 -I 指定 header 位置 問題二:找不到 shared library$ clang++ sample.cpp -I include/ /tmp/sample-2e7dd8.o: In function `main': sample.cpp:(.text+0x1e): undefined reference to `leveldb::Options::Options()' sample.cpp:(.text+0x6f): undefined reference to `leveldb::DB::Open(leveldb::Options const&, std::string const&, leveldb::DB**)' sample.cpp:(.text+0x10c): undefined reference to `leveldb::Status::ToString() const' sample.cpp:(.text+0x7d0): undefined reference to `leveldb::Status::ToString() const' clang: error: linker command failed with exit code 1 (u…

除錯技巧:在 Ubuntu 上找出第三方函式庫的程式碼

這篇藉由一個小例子說明如何使用 gdb, locate, apt-file, apt-get 找出問題原因。藉由取得第三方函式庫的程式碼,可以減少瞎猜的時間。 問題我發現某個程式會不預期的結束。但它不是 crash,沒有 core dump 可看。 用 gdb 找出怎麼結束的先用 gdb attach 程式,繼續操作。程式結束時 gdb 顯示是呼叫 exit() 結束的。 於是再執行一次,這次用 gdb 在 exit 設中斷點再繼續執行。取得的 backtrace 如下: #0 __GI_exit (...) at exit.c:104 #1 0x00007fdd27f60408 in _XDefaultError (...) at ../../src/XlibInt.c:1414 #2 0x00007fdd27f6054b in _XError (...) at ../../src/XlibInt.c:1463 #3 0x00007fdd27f5d5e7 in handle_error ...) at ../../src/xcb_io.c:213 #4 0x00007fdd27f5e687 in _XReply (...) at ../../src/xcb_io.c:699 #5 0x00007fdd27f45346 in XGetWindowProperty (...) at ../../src/GetProp.c:69 #6 0x00007fdd2825db30 in XmuClientWindow () from /usr/lib/x86_64-linux-gnu/libXmu.so.6 ... 看 backtrace 沒什麼頭緒,都是第三方函式庫的程式。照 XmuClientWindow() 的說明,它可能會失敗,但它不該直接呼叫 exit()。先找 XmuClientWindow 的原始碼,看看有什麼線索。 用 Ubuntu 的 package 系統找出原始碼首先用 apt-file 找出 libXmu.so.6 在那個套件 (第一次執行需先跑 apt-file update 更新索引): $ apt-file search /usr/lib/x86_64-linux-gnu/libXmu.so.6 libxmu6: /usr/lib…

NAT64 和 DNS 64

參考資料NAT64 and DNS64 in 30 minutesDNS64與NAT64的網路佈署圖 IPv4 要用完了 (喊了十幾年, 最近是玩真的了), 在骨幹和 server 都轉成 IPv6 的過渡期, 用戶端也要轉換, 不然 server 是轉心酸的。但是大量 server 還是用 IPv4, 所以要讓 client 能同時支援 IPv4 和 IPv6才行。如果你是網管, 希望讓用戶可以同時連 IPv4 和 IPv6 的位置, 一個可能的作法是建置「純 IPv6 環境」, 永遠拿到 IPv6 位置, 永遠連 IPv6 的位置。但要讓 IPv6 client 也能連 IPv4 位置, 需要 NAT64+DNS64 幫忙處理。 原理是 DNS64 會同時查 IPv6 和 IPv4 的位置, 有 IPv6 就用 IPv6, 沒有就轉換 IPv4 為 IPv6, prefix 配合 NAT64 的設定, 讓 client 連往該 IP 的封包會先經過 NAT64 router。第二份 slide 有詳細的流程圖。 然後 NAT64 會再轉換 IPv6 的封包成 IPv4 出去, 無縫接上用 IPv4 位置的 server。至於 client 收到 DNS64 回應的正常 IPv6 位置, 就透過一般 router 直接出去, 不用經過 NAT 64。 對設計後端 server 的人來說, 有愈多用戶可以連 IPv6 位置, 有愈高的機會考慮用 IPv6 位置。對 app 開發者來說, 了解有些用戶的網路環境會用 DNS64+NAT64 的配置, 所以要用 domain name 連上自家 server, 這樣自家 server 用 IPv4 或 IPv6 都會通。