Tuesday, March 2, 2010

Hello World code size (1)

目的為...
  • 觀察簡單程式使用不同編譯方式得到的結果有何不同。
  • 以用不同編譯方式找出較小的code size,以及他們之間的差異。
  • 最後找出減少code size的方式。
    Source code如下...

    1 /*
    2 * File name : helloworld.c
    3 */
    4
    5 #include <stdio.h>
    6
    7 int main(void)
    8 {
    9
    10 printf("Hello World\n");
    11
    12 return 0;
    13 }
    14

    用了以下四種不同的編譯參數以及其結果...

    $ gcc helloworld.c -o helloworld
    $ ls -l helloworld
    -rwxr-xr-x 1 lungswu lungswu 6159 2010-02-24 22:57 helloworld
    $
    $ gcc helloworld.c -o helloworld -O3
    $ ls -l helloworld
    -rwxr-xr-x 1 lungswu lungswu 6141 2010-02-24 22:57 helloworld
    $
    $ gcc helloworld.c -o helloworld -static
    $ ls -l helloworld
    -rwxr-xr-x 1 lungswu lungswu 558138 2010-02-24 22:58 helloworld
    $
    $ gcc helloworld.c -o helloworld -static -O3
    $ ls -l helloworld
    -rwxr-xr-x 1 lungswu lungswu 558740 2010-02-24 22:58 helloworld
    $

    發現以上四種編譯方式中,使用"gcc helloworld.c -o helloworld -O3"的編譯方式可以產生最小的code size(總共6141 bytes)

    但是有一點需注意:編譯的時候加入"-static",code size變的很大....
    原因無它,這是因為一般程式在做連結/執行的時候,會需要用到額外標準函式庫,很明顯的此HelloWorld程式於執行時會連結標準函式庫(libc),且至少printf()此函數為libc之中的一函數。

    一般程式於編譯時,會將這些標準函式庫的函式主體放於別的檔案,程式於執行時再由OS(loader)判斷,且適時載入記憶體之中供執行中程式呼叫使用,此種機制稱做為"動態聯結"(dynamically link)。
    反之,若連結程式時將這些函數一起連結於程式之中,稱之為靜態連結(statically link),可以以-static指定為靜態連結。
    由於靜態連結會將標準函式庫編入程式之中,所以程式大小會差很多,有558740/6141=91倍之多。

    要如何判別一檔案是動態連結還是靜態連結,可以用UNIX下的一個command:"file"

    $ gcc helloworld.c -o helloworld
    $ file helloworld
    helloworld: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.8, not stripped
    $
    $
    $ gcc helloworld.c -o helloworld -static
    $ file helloworld
    helloworld: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.8, not stripped
    $

    另外一個問題,要知道動態聯結的程式有用到哪些額外的函式庫?可以使用"ldd" command。
    由以下的實做可以得知,執行檔"helloworld"會使用到"linux-gate.so.1","libc.so.6"以及"/lib/ld-linux.so.2"此三的動態函式庫。

    $ ldd helloworld
    linux-gate.so.1 => (0xb7fa2000)
    libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb7e36000)
    /lib/ld-linux.so.2 (0xb7fa3000)
    $
  • No comments:

    Post a Comment