void foo() { printf("inside foo()"); int x = 6; x += 2; }
int main() { int x = 0; x = x + 2; foo(); printf("x = %d\n", x); x = 4; return 0; }
編譯它
1
gdb -g -o test test.c
使用gdb來玩玩看,最簡單的用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
$ gdb test (gdb) start Temporary breakpoint 1, main () at test.c:10 10 int x = 0; (gdb) record (gdb) next 11 x = x + 2; (gdb) disp x 1: x = 0 (gdb) next 12 foo(); 1: x = 2 (gdb) reverse-next 11 x = x + 2; 1: x = 0
在使用之前,要先用record記錄操作順序,才有機會還原狀態。不用的時候可以使用record stop停止。 接著常用的step, next, stepi跟nexti都有逆向版。可以參考GDB and Reverse Debugging。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
(gdb) b 15 Breakpoint 2 at 0x400578: file test.c, line 15. (gdb) continue Continuing. inside foo()x = 2
Breakpoint 2, main () at test.c:15 15 return 0; (gdb) b foo Breakpoint 3 at 0x400524: file test.c, line 4. (gdb) reverse-continue Continuing.
Breakpoint 3, foo () at test.c:4 4 printf("inside foo()");
public class RedPimple extends Thread { private boolean done; private int value; @Override public void run() { while (!done) //A Thread.yield(); System.out.println(value); // D } public void done() { done = true; } public void setValue(int value) { this.value = value; } public static void main(String[] args) { RedPimple r = new RedPimple(); r.start(); r.setValue(1); // B r.done(); // C } }
class Foo { private Helper helper = null; public Helper getHelper() { if (helper == null) // A synchronized(this) { if (helper == null) helper = new Helper(); } return helper; } // other functions and members... }
其中的helper = new Helper()其實是以下述句組成。
1 2 3
Allocate memory to tmp // B Invoke Helper constructor from tmp // C Assin helper to tmp; // D
在JDK5之前,沒有任何保證以上的述句會按照想像的順序執行,就算編譯器繞路避掉,CPU也有本事做同樣的事,可能C的執行順序在D之後。當一個Thread先執行D,卻捱沒初始化完成,另一個Thread剛好跑到’A’的點,拿到一個可能有問題的物件。就出事了。 因此語言創造者提出了Happens-Before Relation Model。主要的兩點是,每個語言的作法不盡相同,不過大都依循Acquire and Release Semantics來發展。 Java的volatile就擁有Acquire and Release Semantics。而兩者的定義如下:
A read-acquire executes before all reads and writes the same thread that follow it in program order A write-release executes after all reads and writes by the same thread that precede it in program order
在關注C++11的食嘔,發現C11標準也在2011年同時發佈。 目前C11的支持肚兜不太夠,因此我是用Pelles C測試。 C11的寫法,相關的資料可以參考[Threads in the new ISO C Standard from 2011](Threads in the new ISO C Standard from 2011)。
auto Person::GetPersonType() -> PersonType { return type_; }
有了decltype之後,城市就能這樣寫了
1 2 3 4 5 6 7 8
template <typename Builder> auto makeAndProcessObject (const Builder& builder) -> decltype( builder.makeObject() ) { auto val = builder.makeObject(); // do stuff with val return val; }
新的Return Value Syntax也應用在Lambda Expression上,有機會再說吧。
## Install yum utils ## $ yum install yum-utils ## Package-cleanup set count as how many old kernels you want left ## $ package-cleanup --oldkernels --count=2
template <typename B, typename T = int> void Bar(B b = B(), T t = T()) {} Bar(10); // Bar<int, int> Bar(10L); // Bar<long, int> Bar(10L, 20L); // Bar<long, long> Bar(); // Compile error, couldn't deduce template parameter ‘B’
同樣的在Function Template overload的時候,也是地雷區。
1 2 3 4 5
template <typename T = int> void Foo(T t = T()) {} template <typename B, typename T = int> void Foo(B b = B(), T t = T()) {} Foo(12L); // Compile error, ‘Foo(long int)’ is ambiguous // void Foo(T) [with T = long int] and void Foo(B, T) [with B = long int; T = int] Foo(); // Compile OK, choose the first function