最近遇到在GitHub frok出來的Branch改爛之後,想要捨棄掉自己的修改,重新跟上Upstream的狀態。
沒想到已經有人解答了
Clean up a fork and restart it from the upstream
GitHub page, section “What should I do if I’m in a bad situation”
就是以下四個指令的組合技
1 | $ git fetch upstream |
最近遇到在GitHub frok出來的Branch改爛之後,想要捨棄掉自己的修改,重新跟上Upstream的狀態。
沒想到已經有人解答了
Clean up a fork and restart it from the upstream
GitHub page, section “What should I do if I’m in a bad situation”
就是以下四個指令的組合技
1 | $ git fetch upstream |
寫一下編譯跟安裝Boost該注意的事,目前先寫Linux下的情況,有時間日後再補上
1 | $ apt-get install g++ g++-4.8 g++-4.8-multilib gcc-4.8-doc libstdc++6-4.8-dbg libstdc++-4.8-doc |
關於bootstrap.sh
的詳細用法可以打./boostrap.sh --help
獲得,。如果不更改--prefix
的話,預設的路徑就是/usr/local
。
1 | $ ./bjam --build-dir=./tmp --stagedir=./build |
關於bjam的常用使用說明可以參照,以下是常用參數
directory
將build過程的中間產物放置目錄底下,方便管理directory
最後編譯完成的Library放置處debug
| release
可以選擇Release 或是 Debug模式static
| shared
選擇build出來的事static library或是sshared librarysingle
| multi
選擇Threading modelstatic
| shared
連結C/C++ Standard Library時,選擇Static library或是Shared library link--with-regex
1 | $ ./bjam install |
在網路上搜尋找到的,兩個名字很像,不過作者不同
在Stackoverflow看到,怕忘記寫下來。
原文在此。
簡單的說就是用auto去接reference。
1 | for (auto& kv : myMap) { |
原文在此。
最簡單的方法是使用Boost
1 | #include <boost/range/adaptor/reversed.hpp> |
如果沒有boost的話也可以土法煉鋼,原文Paul的方法不能使用,選用下面Jive的方案
1 | template<class Fwd> |
相信大家都有用過grep來找文字,不過這個ack是專為程式設計師開發的。
從官網下載並安裝
1 | $ curl http://beyondgrep.com/ack-2.12-single-file > ack |
ack有以下這些特性
.svn
和.git
等幾個常用的功能
eat
而忽略掉feature
和`eating1 | $ ack -w eat |
1 | $ ack -Q '$path/$' |
1 | $ ack about --ignore-dir=downloads |
以Makefile為例,可能的檔名有 *.mk, makefile, Makefile
我們想知道這些檔案裡面哪些定義了CFLAGS
,就能夠這樣作
1 | $ ack --make -l CFLAG |
1 | $ tail -f /var/log/syslog | ack --passthru 192.168.1.10 |
這裡的passthru是不管有沒有匹配到都會輸出。
在網路上釉看到ag這套軟體。用途大同小異。多了一些ack沒有的功能。
可以參考Conquering the Command Line Chapter 2. Ack/Ag
既然git是個自由度很高的version control system,對於該怎麼工作這件事,也沒有什麼固定答案,除了當SVN那樣子用法之外,還有其他答案,因此就有這篇文章的產生。
重點只有三個
這是上面那種方式的無敵加強版
有鑑於上面那種方式太複雜,又衍生出來的新方式,也是GitHub自己在用的工作流程。感覺很像第一種方式,不過加上了Code review的能力。
master branch必須是deployable
每個功能fork出branch,push到remote repository
發送pull request
master developer會Review code且merge to master
這篇 Why Github Flow Better? 簡單介紹了git flow跟github flow的優缺點。
[Git Tutorials] (https://www.atlassian.com/git/workflows)簡介了大部分的Git flow。
這兩個工具都是Valgrind的一部分,用途也相同,檢查Thread error,不過用的策略不同,可以交替使用檢茶室否有無隱藏的錯誤。
以下是從Binary hacks抄下的範例
1 | #include <pthread.h> |
裡面有兩個錯誤,一個是count在multi-thread的情況沒有保護,這種情況也可以用下面的thread-sanitizer
偵測出來。
另外一種情況就是lock的順序不同,導致Deadlock的情景。
編譯且執行
1 | $ gcc demo.c -o demo -lpthread |
輸出太長,列出感興趣的部份
==5172== Possible data race during write of size 4 at 0x600C90 by thread #3
==5172== Locks held: none
==5172== at 0x40065F: incr_count (in /home/hungming/a)
==5172== by 0x4C2DB38: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5172== by 0x4E3BE99: start_thread (pthread_create.c:308)
==5172==
==5172== This conflicts with a previous write of size 4 by thread #2
==5172== Locks held: none
==5172== at 0x40065F: incr_count (in /home/hungming/a)
==5172== by 0x4C2DB38: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5172== by 0x4E3BE99: start_thread (pthread_create.c:308)
上面這編列出可能有data-race的情形。
==5172== Thread #5: lock order “0x600CA0 before 0x600CC8” violated
==5172==
==5172== Observed (incorrect) order is: acquisition of lock at 0x600CC8
==5172== at 0x4C2DFCD: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5172== by 0x4006FB: lock_m2_then_m1 (in /home/hungming/a)
==5172== by 0x4C2DB38: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5172== by 0x4E3BE99: start_thread (pthread_create.c:308)
==5172==
==5172== followed by a later acquisition of lock at 0x600CA0
==5172== at 0x4C2DFCD: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5172== by 0x40070B: lock_m2_then_m1 (in /home/hungming/a)
==5172== by 0x4C2DB38: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5172== by 0x4E3BE99: start_thread (pthread_create.c:308)
這邊告訴我們lock的順序不對。
更多的使用方法可以參考
Helgrind使用說明
DRD使用說明
thread-sanitizer現在已經是LLVM的一部分,在編譯LLVM的時候就會編譯完成,而GCC 4.8之後也支援thread-sanitizer。
這跟上面的不同是檢查data-race issue。
寫個sample code
1 | #include <pthread.h> |
這個範例很簡單,可以看出 Global 在不同Thread下操作可能出現問題。
編譯且執行,注意要加上-fsanitize=thread
1 | $ clang simple_race.c -fsanitize=thread -g |
同樣列出我們所關心的部份
WARNING: ThreadSanitizer: data race (pid=4441)
Location is global ‘Global’ of size 4 at 0x7f4d31e90ad8 (a+0x0000016caad8)
SUMMARY: ThreadSanitizer: data race ??:0 Thread2
有了Tool之後,從Log分西問題出在哪就便得很重要了。
在網路上搜尋了一下,發現這功能真是好用。
原先的git submodule缺點不少,一堆批評的聲音。因此之後就有git subtree的誕生,,官方也建議用git subtree解決大部分的問題。
主要應用在兩個場景
假設在我們的Repository當中,需要引用另一個Repository(如Application需要3rd party library)的內容時,盡其希望其Repository能夠跟著更新,一旦我們對其修改時,也能擁有修改和提交的權利。
1 | $ git remote -f add <name of sub_repo> <address of sub_repo> |
第一個指令加上-f
是建立關聯之後再度進行fetch作業。
而第二個指令加上--squash
是要把Sub Repository的history合併成一個。
例如
1 | $ git remote add -f ai https://github.com/aoxu/ai.git |
一旦Sub Repository有人更改之後,我們希望把修改的東西合併到我們 Repository中。
1 | $ git fetch <name of sub_repo> <branch> |
這就類似上面的情況了,一樣給的範例
1 | $ git fetch ai master |
Push只需要一個步驟
1 | $ git subtree push --prefix=<name of sub_directory> <name of sub_repo> <branch> |
同樣有個範例
1 | $ git subtree push --prefix=ai ai master |
如果不用git subtree的話,也有個Subtree merge strategy見仁見智了。
參考資料:
這剛好跟上面那個使用奇境相反,使用方式如下
1 | $ git subtree split -P <sub_directory> -b <branch> |
1 | $ mkdir <new-repo> && cd <new-repo> |
1 | $ git remote add origin <git@github.com:my-user/new-repo.git> |
參考資料:
看了書之後豁然開朗啊,之前還真是個半調子。總結一下使用情境。
1 | struct Obj { |
這段程式碼最大的問題就是,如果ObjFactory的instance沒被摧毀,所有拿到的Obj都不會被釋放。
在ObjectFactory的部份不要保存shared_ptr,這樣會增加reference count,用weak_ptr取而代之。需要的話再promotion成shared_ptr。
1 | class ObjFactory { |
看起來沒什麼問題,不過譽到以下這種情況就爛了
1 | for (int i = 0; i < 3; i++) |
我們希望看到的是每次都能拿到一個新物件,結果發現只有第一次能成功。原因出在當Obj被摧毀的時候,沒有順便清理掉ObjFactory 當中的lookup_的資料,以致於下一次使用的時候,可以找到上一次殘留的屍體,promtion之後就是一個空的shared_ptr。
解決方法就是使用shared_ptr時,同時自訂一個destructor,除了釋放memory之外,也把map裡面的資料輕空。
1 | class ObjFactory { |
現在看起來正常了,不過街下來這個Case又會遇到問題。
1 | { |
由於在這個block之內,pFactory已經被釋放了,所以那個destructor的this一點都不可靠,因此要把裡面那個this
轉成一個shared_ptr。
enable_shared_from_this就是因此登場的,他可以把this指標所在的位置轉成一個shared_ptr。
而原先的測試部份也必須用shared_ptr管理了。
1 | class ObjFactory : public enable_shared_from_this<ObjFactory> { |
使用shared_ptr會延長ObjectFactory的LifeCycle,如果pFactory已經不在的話,跟本連清理的動作都不用作。
所以程式可以寫成
1 | class ObjFactory : public enable_shared_from_this<ObjFactory> { |
有本好書真的很重要啊,以前我只會用最粗淺的shared_ptr,對於wear_ptr跟其他特性玩全部熟。有了範例之後至少有個基本認識。
至於程式寫得這麼複雜到令人髮指也是不太好,Garbage collection很大部份可以紓解Programmer的負擔。