0%

之前實驗出來的結果,做個筆記,以免日後忘記。

由於現在的C++編譯器都會做某種程度的最佳化,以GCC來當範本,加上-fno-elide-constructors 參數避免Copy elision

以下是我們的程式碼。

而第一版的執行結果如下

1
2
3
4
5
6
7
Constructing! 1
Copy constructing! 2
Destructing.. 1
Copy constructing! 3
Destructing.. 2
before return
Destructing.. 3

從結果我們可以發現,get函數裡面的f,就是id為1的物件,而這個物件在函數結束之後就結束生命週期。而id為2的物件就是get回傳的暫時物件。當回傳時會複製f的內容,而生命週期在main中的foo f = get();之後也跟著消失,從這邊可以看到,我們產生了一個物件,複製了兩份物件,如果當物件體積大的時候,大量的複製/銷燬這種損失是巨大的。

接著介紹
Returning temporary object and binding to const reference
第二版的程式碼

來看執行結果

1
2
3
4
5
Constructing! 1
Copy constructing! 2
Destructing.. 1
before return
Destructing.. 2

看到少了一個Object生成,這是由於C++ Standards Temporary objects 中有這麼一段話。

A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits.

所以這個暫時物件的生命週期就跟main的生命週期一樣長,無需再複製一份。

在Linux下尋找text pattern的方法。
方法一:使用 find 跟 xargs 共同使用

find dir/ | xargs grep str

這方法會搜尋底下的子目錄

find file | xargs grep str

搜尋檔案裡面是否出現text pattern

方法二: 直接使用grep

grep [-r] str dir/*

搜尋目錄下的所有檔案,-r表示是否蓮子目錄一起搜尋

grep str file

搜尋檔案裡面是否出現text pattern

記錄一下JNI的建立跟使用方法,在Linux底下驗證成功。
以下是一個簡單的範例

裡面做的事情很簡單,載入Shared Object,呼叫 Native Code。

第一步: 接著編譯 Java Code 產生 class 檔

1
$ javac HelloWorld.java

第二步: 產生 HelloWorld.h Header File

1
$ javah -jni HelloWorld.

產生出來的 Header File長這個樣子

第三步: 撰寫對應的Native Code
做的事情也很簡單,就是印出Hello World而已

第四步: 產生 Shared Object

1
$ gcc -I"/usr/lib/jvm/java-7-openjdk-amd64/include" -fPIC -shared -o libHelloWorld.so HelloWorld.c

此時libHelloWorld.so會跟HelloWorld.class在同一個目錄中
第五步: 執行,將LibraryPath指向當前目錄

java -Djava.library.path=pwd HelloWorld

可以看到正確的結果。

之前是介紹如何從 Java 呼叫 C++ 的 Native Code,現在要說的是如何從C++建立 Java Virtual Machine,進而執行 Java Code。

第一步: 寫好Java Code且編譯
這裡準備的 Java Code

編譯它

1
$ javac HelloWorld.java

第二步:撰寫C++的程式碼且編譯

編譯它

1
$ g++ -I"/usr/lib/jvm/java-7-openjdk-amd64/include"  -L"/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server" Hello.cpp -ljvm -o Hello

第三歩: 設定 LD_LIBRARY_PATH

1
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server

第四歩: 執行程式

1
$ ./Hello

gropf是gnu工具之一,在編譯的時候加入了profiling的source code,執行時統計user space的執行資料,可以得到每個function的被呼叫次數,執行時間,呼叫關係等。

以下是一個簡單範例

##Quick Start

先用gcc編譯程式

1
gcc hello.c -o hello -pg -g

-pg表示開啟profiling功能,如果要得到帶注視的程式碼清單,需加上-g。

執行程式

1
./hello

此時會產生 gmon.out檔

使用gprof對程式進行分析

1
gprof hello gmon.out -p

得到每個函數所佔用的執行時間

1
gprof hello gmon.out -q

得到call graph,每個函數的呼叫關係,

1
gprof hello gmon.out -A

得到帶注釋的source code清單,列出每個函數的呼叫次數。