2021年1月9日 星期六

gcc option: --gc-sections -ffunction-sections -fdata-section

the 1st edition: 20191121
--gc-sections -ffunction-sections -fdata-section 這些選項是搭配用的, --gc-sections 是 ld option, -ffunction-sections -fdata-section 是 compiler 用的。
  1. 使用--gc-section编译选项减小程序体积
  2. -ffunction-sections -Wl,--gc-sections
這兩篇文章說明了這些選項的功用, 我主要以實際的例子做個補充。

k.c 有個 abc(), abc() 呼叫了 def(), 但是 def() 沒有定義, 學校教學或是書上的 c 語言書籍一定會跟你說這樣是編譯不過的, 會有 linking error。

k.c
 1 
 2 void def();
 3 
 4 void abc()
 5 {
 6   def();
 7 }
 8 
 9 int xyz(int a)
10 {
11   return a+2; 
12 }
13 
14 int main(void)
15 {
16   return xyz(3);
17 }

但在現實的工程上就是會有些不同, 運用了編譯器/連結器的特異功能, 這個程式是可以正確編譯的。因為 main() 根本沒呼叫 abc(), 如果只編譯/連結 main(), xyz() 應該就可以過關, 這便是 --gc-sections, -ffunction-sections 的組合技用法。

list 2
$ g++ -o k k.cpp
/usr/bin/ld: /tmp/ccLiBePh.o: in function `abc()':
k.cpp:(.text+0x5): undefined reference to `def()'
collect2: error: ld returned 1 exit status

list 3
$ g++ -o k k.cpp -Wl,--gc-sections -ffunction-sections

list 2. 沒有 -Wl,--gc-sections, 有預期的 linking error, 沒有定義 def(); list 3 加入了 -Wl,--gc-sections, 成功 link。

原理就是第一篇文章說的那樣, 需要理解 section 這個東西, 才能理解文章的內容。

來看看他們的 section 有何不同。 list 5 L27 只有 .text section, 並沒有為每一個 function 產生一個 section。

list 5 k.o
 1 ELF Header:
 2   Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
 3   Class:                             ELF64
 4   Data:                              2's complement, little endian
 5   Version:                           1 (current)
 6   OS/ABI:                            UNIX - System V
 7   ABI Version:                       0
 8   Type:                              REL (Relocatable file)
 9   Machine:                           Advanced Micro Devices X86-64
10   Version:                           0x1
11   Entry point address:               0x0
12   Start of program headers:          0 (bytes into file)
13   Start of section headers:          840 (bytes into file)
14   Flags:                             0x0
15   Size of this header:               64 (bytes)
16   Size of program headers:           0 (bytes)
17   Number of program headers:         0
18   Size of section headers:           64 (bytes)
19   Number of section headers:         12
20   Section header string table index: 11
21 
22 Section Headers:
23   [Nr] Name              Type             Address           Offset
24        Size              EntSize          Flags  Link  Info  Align
25   [ 0]                   NULL             0000000000000000  00000000
26        0000000000000000  0000000000000000           0     0     0
27   [ 1] .text             PROGBITS         0000000000000000  00000040
28        0000000000000030  0000000000000000  AX       0     0     1
29   [ 2] .rela.text        RELA             0000000000000000  00000270
30        0000000000000030  0000000000000018   I       9     1     8
31   [ 3] .data             PROGBITS         0000000000000000  00000070
32        0000000000000000  0000000000000000  WA       0     0     1
33   [ 4] .bss              NOBITS           0000000000000000  00000070
34        0000000000000000  0000000000000000  WA       0     0     1
35   [ 5] .comment          PROGBITS         0000000000000000  00000070
36        000000000000001e  0000000000000001  MS       0     0     1
37   [ 6] .note.GNU-stack   PROGBITS         0000000000000000  0000008e
38        0000000000000000  0000000000000000           0     0     1
39   [ 7] .eh_frame         PROGBITS         0000000000000000  00000090
40        0000000000000078  0000000000000000   A       0     0     8
41   [ 8] .rela.eh_frame    RELA             0000000000000000  000002a0
42        0000000000000048  0000000000000018   I       9     7     8
43   [ 9] .symtab           SYMTAB           0000000000000000  00000108
44        0000000000000138  0000000000000018          10     8     8
45   [10] .strtab           STRTAB           0000000000000000  00000240
46        000000000000002c  0000000000000000           0     0     1
47   [11] .shstrtab         STRTAB           0000000000000000  000002e8
48        0000000000000059  0000000000000000           0     0     1
49 Key to Flags:
50   W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
51   L (link order), O (extra OS processing required), G (group), T (TLS),
52   C (compressed), x (unknown), o (OS specific), E (exclude),
53   l (large), p (processor specific)
54 
55 There are no section groups in this file.
56 
57 There are no program headers in this file.
58 
59 There is no dynamic section in this file.
60 
61 Relocation section '.rela.text' at offset 0x270 contains 2 entries:
62   Offset          Info           Type           Sym. Value    Sym. Name + Addend
63 00000000000a  000a00000004 R_X86_64_PLT32    0000000000000000 def - 4
64 00000000002a  000b00000004 R_X86_64_PLT32    0000000000000011 xyz - 4
65 
66 Relocation section '.rela.eh_frame' at offset 0x2a0 contains 3 entries:
67   Offset          Info           Type           Sym. Value    Sym. Name + Addend
68 000000000020  000200000002 R_X86_64_PC32     0000000000000000 .text + 0
69 000000000040  000200000002 R_X86_64_PC32     0000000000000000 .text + 11
70 000000000060  000200000002 R_X86_64_PC32     0000000000000000 .text + 20
71 
72 The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
73 
74 Symbol table '.symtab' contains 13 entries:
75    Num:    Value          Size Type    Bind   Vis      Ndx Name
76      0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
77      1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS k.c
78      2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
79      3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
80      4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
81      5: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
82      6: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
83      7: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
84      8: 0000000000000000    17 FUNC    GLOBAL DEFAULT    1 abc
85      9: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_
86     10: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND def
87     11: 0000000000000011    15 FUNC    GLOBAL DEFAULT    1 xyz
88     12: 0000000000000020    16 FUNC    GLOBAL DEFAULT    1 main
89 
90 No version information found in this file.

list 6 L33, 37, 39 為每一個 function 產生一個 section, 這樣 linker 就可以把 .text.abc section 移除, 就可以輸出 elf 執行檔。

list 6. k.gc-section.o
  1 ELF Header:
  2   Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  3   Class:                             ELF64
  4   Data:                              2's complement, little endian
  5   Version:                           1 (current)
  6   OS/ABI:                            UNIX - System V
  7   ABI Version:                       0
  8   Type:                              REL (Relocatable file)
  9   Machine:                           Advanced Micro Devices X86-64
 10   Version:                           0x1
 11   Entry point address:               0x0
 12   Start of program headers:          0 (bytes into file)
 13   Start of section headers:          944 (bytes into file)
 14   Flags:                             0x0
 15   Size of this header:               64 (bytes)
 16   Size of program headers:           0 (bytes)
 17   Number of program headers:         0
 18   Size of section headers:           64 (bytes)
 19   Number of section headers:         16
 20   Section header string table index: 15
 21 
 22 Section Headers:
 23   [Nr] Name              Type             Address           Offset
 24        Size              EntSize          Flags  Link  Info  Align
 25   [ 0]                   NULL             0000000000000000  00000000
 26        0000000000000000  0000000000000000           0     0     0
 27   [ 1] .text             PROGBITS         0000000000000000  00000040
 28        0000000000000000  0000000000000000  AX       0     0     1
 29   [ 2] .data             PROGBITS         0000000000000000  00000040
 30        0000000000000000  0000000000000000  WA       0     0     1
 31   [ 3] .bss              NOBITS           0000000000000000  00000040
 32        0000000000000000  0000000000000000  WA       0     0     1
 33   [ 4] .text.abc         PROGBITS         0000000000000000  00000040
 34        0000000000000011  0000000000000000  AX       0     0     1
 35   [ 5] .rela.text.abc    RELA             0000000000000000  000002b8
 36        0000000000000018  0000000000000018   I      13     4     8
 37   [ 6] .text.xyz         PROGBITS         0000000000000000  00000051
 38        000000000000000f  0000000000000000  AX       0     0     1
 39   [ 7] .text.main        PROGBITS         0000000000000000  00000060
 40        0000000000000010  0000000000000000  AX       0     0     1
 41   [ 8] .rela.text.main   RELA             0000000000000000  000002d0
 42        0000000000000018  0000000000000018   I      13     7     8
 43   [ 9] .comment          PROGBITS         0000000000000000  00000070
 44        000000000000001e  0000000000000001  MS       0     0     1
 45   [10] .note.GNU-stack   PROGBITS         0000000000000000  0000008e
 46        0000000000000000  0000000000000000           0     0     1
 47   [11] .eh_frame         PROGBITS         0000000000000000  00000090
 48        0000000000000078  0000000000000000   A       0     0     8
 49   [12] .rela.eh_frame    RELA             0000000000000000  000002e8
 50        0000000000000048  0000000000000018   I      13    11     8
 51   [13] .symtab           SYMTAB           0000000000000000  00000108
 52        0000000000000180  0000000000000018          14    11     8
 53   [14] .strtab           STRTAB           0000000000000000  00000288
 54        000000000000002c  0000000000000000           0     0     1
 55   [15] .shstrtab         STRTAB           0000000000000000  00000330
 56        000000000000007d  0000000000000000           0     0     1
 57 Key to Flags:
 58   W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
 59   L (link order), O (extra OS processing required), G (group), T (TLS),
 60   C (compressed), x (unknown), o (OS specific), E (exclude),
 61   l (large), p (processor specific)
 62 
 63 There are no section groups in this file.
 64 
 65 There are no program headers in this file.
 66 
 67 There is no dynamic section in this file.
 68 
 69 Relocation section '.rela.text.abc' at offset 0x2b8 contains 1 entry:
 70   Offset          Info           Type           Sym. Value    Sym. Name + Addend
 71 00000000000a  000d00000004 R_X86_64_PLT32    0000000000000000 def - 4
 72 
 73 Relocation section '.rela.text.main' at offset 0x2d0 contains 1 entry:
 74   Offset          Info           Type           Sym. Value    Sym. Name + Addend
 75 00000000000a  000e00000004 R_X86_64_PLT32    0000000000000000 xyz - 4
 76 
 77 Relocation section '.rela.eh_frame' at offset 0x2e8 contains 3 entries:
 78   Offset          Info           Type           Sym. Value    Sym. Name + Addend
 79 000000000020  000500000002 R_X86_64_PC32     0000000000000000 .text.abc + 0
 80 000000000040  000600000002 R_X86_64_PC32     0000000000000000 .text.xyz + 0
 81 000000000060  000700000002 R_X86_64_PC32     0000000000000000 .text.main + 0
 82 
 83 The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
 84 
 85 Symbol table '.symtab' contains 16 entries:
 86    Num:    Value          Size Type    Bind   Vis      Ndx Name
 87      0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
 88      1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS k.c
 89      2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
 90      3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
 91      4: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
 92      5: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
 93      6: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
 94      7: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
 95      8: 0000000000000000     0 SECTION LOCAL  DEFAULT   10 
 96      9: 0000000000000000     0 SECTION LOCAL  DEFAULT   11 
 97     10: 0000000000000000     0 SECTION LOCAL  DEFAULT    9 
 98     11: 0000000000000000    17 FUNC    GLOBAL DEFAULT    4 abc
 99     12: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_
100     13: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND def
101     14: 0000000000000000    15 FUNC    GLOBAL DEFAULT    6 xyz
102     15: 0000000000000000    16 FUNC    GLOBAL DEFAULT    7 main
103 
104 No version information found in this file.

2020年12月27日 星期日

20201119 付款 DD エリカ・フォンティーヌ 61000

https://dollfie.ec.volks.co.jp/ext/1st_anniversary/index.html

ドルフィーオンラインストア1周年記念フェア【GL/VS/VIP会員様限定】SD・DDベストセレクション抽選販売

這是一個抽選活動, 需要 GL 以上等級的會員才能參加, 有很多娃可以抽, 選了「綾瀨亞美」、「エリカ」參加。

公佈日期如果沒收到 email, 應該就是沒中, 這次運氣不好, 第一時間都沒收到, 不過後來補收到「エリカ」, 可能是有人沒繳錢, 空出來的名額, 據說抽到沒去繳款會被 volks 鎖帳號。

109/11/25  VOLKSHOBBYTENGOKUWE100001  109/12/02  109/11/30/JPY   67,128.00/JPN   18393
109/11/25  國外交易服務費 (簽帳 18,393)  109/12/02  TWD             276
其實並沒有特別喜歡「エリカ」, 單純想要 DD3 身體, 現在已經都沒有 DD3, 販售的都是 DDf3, DDf3 的大腿股那邊有卡筍, 需要對準裝上, 我覺得那邊真的不好組裝, 已經脫落好幾次, 每次重裝都很痛苦。

而「エリカ」的槍看起來還不錯, 衣服造型也蠻特別, 就選她了。後來才知道是櫻花大戰的角色。

「エリカ」- 2013年12月22日 ドールズ・パーティー30にて販売, 是 2013 的娃, 這個不會是庫存吧!

另外一個 DD3 身體的 Ruri 因為已經抽選了 2 隻, 不想再加重負擔了, 全中就慘了 (發現是自己想太多), 考慮良久最後沒抽。

Your order has been completed.
Thank you for VOLKS official Dollfie Online Store

[ご注文番号:100398230]

2020/11/27 寄出
國際及大陸各類郵件查詢
郵件號碼:
EJ781985185JP
※受新型冠狀病毒肺炎(COVID-19)影響,郵遞時效均大幅延誤。
目前最新處理結果
狀態
處理日期時間
處理單位
詳細資料
離開寄達國互換局
2020/11/30 - 11:31:19
特種郵件股
課稅金額:: NT$ 843
本件將轉往:郵局快捷股

 
郵件詳細處理過程
狀態
處理日期時間
處理單位
詳細資料
海關查驗
2020/11/29 - 18:31:24
台北郵件中心包進股
到達寄達國互換局
2020/11/29 - 17:35:13
台北郵件中心包進股
原寄國:日本
出口局:OSAKA INT
總包號碼:1996
已出口-資料詳如右方
2020/11/28 - 07:00:00
日本
目的國:中華民國
目的互換局:TAIPEI
總包號碼:
交寄郵件
2020/11/27 - 19:47:00
目的國:中華民國
這次一樣被課稅, 843 台幣。



エリカ的包裝比較簡單, 不像 2b, 有一個外盒, 可以拖出整個內盒, エリカ的包裝是直接打開, 一個簡單的ㄇ字型紙片, 分隔 2 層, 一個是娃體本身, 另外一邊就是衣服和裝備。

裝備有 2 樣, 一把長槍, 看起來作工沒特別精細, 需要簡單組合一下, 之前還以為是十字弓之類的武器; 另外一個是搖鈴嗎? 搖一搖會有聲音, 應該是一種樂器吧!



頭髮有點亂, 而且有點捲, 不知道怎麼整理, 所以看起來亂亂的。



2020年12月20日 星期日

20201219 拔智齒

嘴巴左上最後一顆牙齒蛀掉了, 破了一個小洞。幾個禮拜前去看牙醫的時候, 牙醫建議我拔掉, 我問可不可以補, 醫生說: 「那個位置不好處理, 而且要挖下去才知道蛀牙有多深。」建議我拔掉。他先用一個臨時的補法先暫時補起來。

我考慮之後還是決定拔掉, 這真是個可怕的決定。20201219 (6) 15:30 到診所報到。

fig 1, 拔下來的智齒
醫生檢查了一下之後, 就打麻醉針了 (15:40), 然後照 X 光, 照 X 光時要咬著一張紙。

醫生評估看起來應該算是好拔, 我自己則是嚇得要死, 非常緊張, 看著醫生拿著工具在嘴上操作, 一直要我放輕鬆, 深呼吸。大概 1, 2 分鐘之後, 醫生便說, 牙齒掉下去了。

麻藥真是偉大的發明, 過程之間沒有痛的感覺, 這次的拔牙很順利。

再來便是止血的部份 (15:45), 要用力咬住紗布, 一個小時左右 (16:45), 這期間都不能說話, 醫生交代一些吃東西的注意事項, 我完全沒記住。

大概就是「拔牙後禁吐口水、用吸管…防感染要做到護理7件事」說的這樣, 請自己注意。

咬著紗布的時候, 會累積口水, 由於在流血, 所以也有一些血水, 文章說可以吞下去, 但我實在不想吞, 但也不能吐出來, 該怎麼辦呢? 我在一小時之後, 不可以吐出紗布, 要用手去拿出來, 然後嘴巴朝下, 將血水、口水倒出來, 要很小心, 不要去動到傷口, 然後有些口水還是留在嘴裏, 用衛生紙去吸出來。這樣口腔內就舒服多了。

如果沒有止血, 就要在咬住紗布, 一樣是咬住一小時。因為晚上牙醫就休息了, 如果有出血狀況, 就需要去掛急診了。如果可以還是在一般時間拔牙比較好, 不要選在星期六。

確認已經止血之後, 就比較安心了, 心情也沒在哪麼緊張。

18:30 之後, 麻藥漸漸地退了, 本來很擔心會開始痛起來, 竟然沒有想像般的疼痛, 運氣不錯。打聽了一些朋友拔智齒的經驗, 有些還遇到很麻煩的處理, 自己運氣算不錯。

fig 1 就是拔下來的智齒, 可以看到破掉一部份, 之前就是臨時補在這邊, 齒面的部份也可以看到蛀的蠻厲害的。如果用補的, 看起來要挖掉不少部份。

晚上刻意很晚才吃飯, 老婆貼心煮了爛爛的粥, 讓我方便進食。用了小湯匙, 慢慢吃掉一碗粥, 吃完整碗粥時, 快要 23:55 了。

經過一番折疼, 總算度過這個可怕的拔牙治療。今天就先不刷牙了, 避免動到傷口。

2020年12月16日 星期三

[購買新機車] 光陽名流 125 abs

fig 1. yamaha 迅光 fig 2. 光陽名流 7 期 - abs


yamaha 迅光陪伴我很久了 (1996), 基本上沒什麼問題, 但最近幾次維修都會遇到可能沒有零件的問題, 有些零件不容易找, 可能會面臨沒有零件可修的狀態。

時速表不會動, 油箱蓋也蓋不緊, 雨水會跑進去。

每次去修車, 師父都會說你可以換車了, 還是不同店家師父說的, 本來還想在撐個幾年, 不過今年有不錯的補助, 我決定換車了。

據說 2020 之後的補助要減少, 所以 202012 一堆買車的人, 我也是趕在這波中。

在光陽看到新名流125 ABS (七期) 扣掉補助大概可以用 55000 買到。就訂車了。

20201215 定了新名流125 ABS - 七期, 定價: 77500

所有補助是 9200 (光陽補貼) + 13300 (分為4筆, 有一筆是 abs 補助 4000)
13300 = 4000 + 300 + 4000 + 5000
300 + 4000 + 5000 是回收舊機車的補助。

只有 9200 是直接扣掉, 所以要付 68300

補助款要等 3,4 個月, 這個可靠嗎? 會不會補助沒過? abs 4000 補助是其中最快核發的, 大概一個月可以拿到。

老闆還說目前都沒車可賣, 只剩下這台, 我偏愛藍色款, 但沒有了。真的是因為補助關係, 所以車賣得那麼好嗎?

這台總公司目前也不接受定車, 說是產能來不及。

但是沒有補助的話, 車廠應該是比人民還怕的, 人民就頂多不買新車, 但車廠的收入可能就會驟減。如果沒補助, 我的迅光還是會一直騎的。

不過看到這篇「[問題] 新名流熄火,小弟差點上天堂」熄火問題之後有點懊惱, 但為時已晚。已經牽回來了, 現在也有點擔心。

覺得很蠢的一點就是大燈是無法關掉的, 一發動, 前後燈就會開啟。另外沒有採著發動的裝置了。

液晶面板感覺很新潮, 不過我還是偏愛指針市的面板。老闆說不用熱車就可以直接騎了。

本來也有考慮 gogoro, 但是其月租方案和電池條款讓我卻步。買了 gogoro 但卻感覺沒有擁有權, 花錢買車, 但是卻是租車的使用體驗。比較想用 goshare 那種租車方案。

gogoro 的月租費是一輩子, 沒辦法像電信業者可以換別家, 這種被掐住脖子的感覺不太舒服 (有點類似中油獨大的感覺), 心理上就不太能接受。而且手機使用月租是有道理的, 你的手機就算不撥出去, 也要時時刻刻使用電信業者的服務, 這樣才能接受打來的電話, 但電池充電並不是這樣, 只有沒電的時候, 才會需要去充電, 用月租實在不合理。

若是剛好有事一段時間不騎, 還要特別去處理, 避免被扣月租費用。我的騎車方式非常不適合月租, 因為我的騎乘公里數不是固定的, 一般會搭配大眾交通工具上下班, 並非一定騎機車, 這種月租方式, 對我這種情況, 相當不友善。

電池的帝王條款更是讓我不舒服, 去中油買油, 雖然中油獨大的感覺一樣令人不舒服, 但買到的油可是屬於我的, 而 gogoro 的電池只能粗, 是無法買斷的, 等於整台機車受制於人, 不想花大錢買這種產品。想得遠一點, 如果 gogoro 倒掉, 機車就不能騎了。但如果可以自己充電, 或是 gogoro 有販售電池, 那至少還可以自己充電。電動車不管是電池還是 gogoro 的充電服務, 最怕就是廠商倒掉, 就無法繼續使用機車, 這是一個麻煩點。

要辦理車牌和一些補助款以及舊車報廢, 需要留下身份證、印章, 存款簿需要影印一份給店家。

ref:
GOGORO的電池合約之討論,好厲害的合約
8 縣市 2020 年電動機車補助出爐,新購補助減少、汰舊換新成主力
Gogoro遲早要面對的法律合約
Gogoro Network™ 智慧電池服務合約
第五條 電池所有權

使用者知悉睿能新動力為 Gogoro Network™ 智慧電池之唯一所有權人,使用者對Gogoro Network™ 智慧電池均未享有所有權、其他物權、智慧財產權或其他任何權利 。除依本合約享有使用 Gogoro Network™ 智慧電池之權利外,使用者不得對 Gogoro Network™ 智慧電池主張或行使所有權、留置權、其他物權或任何權利,且使用者無權將Gogoro Network™ 智慧電池之任何權利或權益轉讓予任何第三人

2020年12月10日 星期四

gcc tail call (tail recursion) optimize

fig 1. C++ 函數式編程
有一陣時間, 沒有去研究一個技術主題之後, 我又回到了 revursive 上, 這是在讀 SICP 之後才注意到的技術。

但是 revursive 實在太難, 我還沒能掌握這個思考方式。

甚至連 tail call (tail recursive) 都搞不清楚, 後來在閱讀了「C++ 函數式編程 (Functional Programming in C++: How to improve your C++ programs using functional techniques)」(fig 1) 之後, 才知道就是字面上的意思。

而只有 tail call 才能讓編譯器有機會轉成 loop, 避免使用 stack。

一般看到的文章都說編譯器會把 tail call 轉成 loop, 而不使用 stack 空間, 避免 stack 爆掉, 這是真的嗎?

要怎麼確認呢?

就像 inline function, 我要怎麼確認真的有 inline 呢?

如果編譯器沒有給出明確訊息, 似乎也只能看編譯器輸出的組合語言了。

我用了 sum.c 來測試, 這個程式就是把 arr[0] ~ arr[4] 印出來, 只是我用了 recursive function 印出, 而不是用 for loop。

這個程式符合 tail call, call 自己的那行程式是在程式的最尾端, 所以應該可以被編譯器最佳化為 loop 才是。但如果沒下什麼編譯選項的話, 是看不到這樣的結果的。

list 1. sum.c
 1 #include <stdio.h>
 2 
 3 void print(int *array, int len, int n)
 4 {
 5   if (n >= len)
 6   {
 7     return;
 8   }
 9   else
10   {
11     printf("n: %d, %d\n", n, array[n]);
12     return print(array, len, n+1);
13   }
14 }
15 
16 int main(int argc, char *argv[])
17 {
18   int arr[] = {1,2,3,4,5,};
19   print(arr, 5, 0);
20   return 0;
21 }


而和 tail recursive calls 有關的編譯選項是 -foptimize-sibling-calls。

-foptimize-sibling-calls
    Optimize sibling and tail recursive calls.

    Enabled at levels -O2, -O3, -Os.


但是很奇怪, 如果使用 -foptimize-sibling-calls 反而不會輸出 Optimize tail recursive calls 的組合語言, 需要用 -Os 才會將 tail recursive calls 轉成 loop。

gcc  -no-pie -m32 sum.c -g -Os -o sum.tc.opt
gcc  -no-pie -m32 sum.c -g -foptimize-sibling-calls -o sum.no.tc.opt


list 2 L37, 在 print() 裡頭還是會 call print()

list 2. sum.no.tc.opt.txt
 3 
 4 sum.no.tc.opt:     file format elf32-i386
 5 
 6 
 7 
 8 08049162 <print>:
 9  8049162:	55                   	push   %ebp
10  8049163:	89 e5                	mov    %esp,%ebp
11  8049165:	53                   	push   %ebx
12  8049166:	83 ec 04             	sub    $0x4,%esp
13  8049169:	e8 b4 00 00 00       	call   8049222 <__x86.get_pc_thunk.ax>
14  804916e:	05 92 2e 00 00       	add    $0x2e92,%eax
15  8049173:	8b 55 10             	mov    0x10(%ebp),%edx
16  8049176:	3b 55 0c             	cmp    0xc(%ebp),%edx
17  8049179:	7d 43                	jge    80491be <print+0x5c>
18  804917b:	8b 55 10             	mov    0x10(%ebp),%edx
19  804917e:	8d 0c 95 00 00 00 00 	lea    0x0(,%edx,4),%ecx
20  8049185:	8b 55 08             	mov    0x8(%ebp),%edx
21  8049188:	01 ca                	add    %ecx,%edx
22  804918a:	8b 12                	mov    (%edx),%edx
23  804918c:	83 ec 04             	sub    $0x4,%esp
24  804918f:	52                   	push   %edx
25  8049190:	ff 75 10             	pushl  0x10(%ebp)
26  8049193:	8d 90 08 e0 ff ff    	lea    -0x1ff8(%eax),%edx
27  8049199:	52                   	push   %edx
28  804919a:	89 c3                	mov    %eax,%ebx
29  804919c:	e8 8f fe ff ff       	call   8049030 <printf@plt>
30  80491a1:	83 c4 10             	add    $0x10,%esp
31  80491a4:	8b 45 10             	mov    0x10(%ebp),%eax
32  80491a7:	83 c0 01             	add    $0x1,%eax
33  80491aa:	83 ec 04             	sub    $0x4,%esp
34  80491ad:	50                   	push   %eax
35  80491ae:	ff 75 0c             	pushl  0xc(%ebp)
36  80491b1:	ff 75 08             	pushl  0x8(%ebp)
37  80491b4:	e8 a9 ff ff ff       	call   8049162 <print>
38  80491b9:	83 c4 10             	add    $0x10,%esp
39  80491bc:	eb 01                	jmp    80491bf <print+0x5d>
40  80491be:	90                   	nop
41  80491bf:	8b 5d fc             	mov    -0x4(%ebp),%ebx
42  80491c2:	c9                   	leave  
43  80491c3:	c3                   	ret    
44 
45 080491c4 <main>:
46  80491c4:	8d 4c 24 04          	lea    0x4(%esp),%ecx
47  80491c8:	83 e4 f0             	and    $0xfffffff0,%esp
48  80491cb:	ff 71 fc             	pushl  -0x4(%ecx)
49  80491ce:	55                   	push   %ebp
50  80491cf:	89 e5                	mov    %esp,%ebp
51  80491d1:	51                   	push   %ecx
52  80491d2:	83 ec 24             	sub    $0x24,%esp
53  80491d5:	e8 48 00 00 00       	call   8049222 <__x86.get_pc_thunk.ax>
54  80491da:	05 26 2e 00 00       	add    $0x2e26,%eax
55  80491df:	c7 45 e4 01 00 00 00 	movl   $0x1,-0x1c(%ebp)
56  80491e6:	c7 45 e8 02 00 00 00 	movl   $0x2,-0x18(%ebp)
57  80491ed:	c7 45 ec 03 00 00 00 	movl   $0x3,-0x14(%ebp)
58  80491f4:	c7 45 f0 04 00 00 00 	movl   $0x4,-0x10(%ebp)
59  80491fb:	c7 45 f4 05 00 00 00 	movl   $0x5,-0xc(%ebp)
60  8049202:	83 ec 04             	sub    $0x4,%esp
61  8049205:	6a 00                	push   $0x0
62  8049207:	6a 05                	push   $0x5
63  8049209:	8d 45 e4             	lea    -0x1c(%ebp),%eax
64  804920c:	50                   	push   %eax
65  804920d:	e8 50 ff ff ff       	call   8049162 <print>
66  8049212:	83 c4 10             	add    $0x10,%esp
67  8049215:	b8 00 00 00 00       	mov    $0x0,%eax
68  804921a:	8b 4d fc             	mov    -0x4(%ebp),%ecx
69  804921d:	c9                   	leave  
70  804921e:	8d 61 fc             	lea    -0x4(%ecx),%esp
71  8049221:	c3                   	ret    


list 3 L65, 在 print() 是用 jmp 回到前面一個點 (L55), 就是 loop 的動作。

list 3. sum.tc.opt.txt
 1 
 2 sum.tc.opt:     file format elf32-i386
 3 
 4 
 5 
 6 Disassembly of section .text:
 7 
 8 08049050 <main>:
 9  8049050:	e8 9b 01 00 00       	call   80491f0 <__x86.get_pc_thunk.ax>
10  8049055:	05 ab 2f 00 00       	add    $0x2fab,%eax
11  804905a:	8d 4c 24 04          	lea    0x4(%esp),%ecx
12  804905e:	83 e4 f0             	and    $0xfffffff0,%esp
13  8049061:	ff 71 fc             	pushl  -0x4(%ecx)
14  8049064:	55                   	push   %ebp
15  8049065:	89 e5                	mov    %esp,%ebp
16  8049067:	57                   	push   %edi
17  8049068:	56                   	push   %esi
18  8049069:	8d b0 14 e0 ff ff    	lea    -0x1fec(%eax),%esi
19  804906f:	8d 45 d4             	lea    -0x2c(%ebp),%eax
20  8049072:	51                   	push   %ecx
21  8049073:	8d 7d d4             	lea    -0x2c(%ebp),%edi
22  8049076:	b9 05 00 00 00       	mov    $0x5,%ecx
23  804907b:	83 ec 30             	sub    $0x30,%esp
24  804907e:	f3 a5                	rep movsl %ds:(%esi),%es:(%edi)
25  8049080:	6a 00                	push   $0x0
26  8049082:	6a 05                	push   $0x5
27  8049084:	50                   	push   %eax
28  8049085:	e8 28 01 00 00       	call   80491b2 <print>
29  804908a:	8d 65 f4             	lea    -0xc(%ebp),%esp
30  804908d:	31 c0                	xor    %eax,%eax
31  804908f:	59                   	pop    %ecx
32  8049090:	5e                   	pop    %esi
33  8049091:	5f                   	pop    %edi
34  8049092:	5d                   	pop    %ebp
35  8049093:	8d 61 fc             	lea    -0x4(%ecx),%esp
36  8049096:	c3                   	ret    
37  8049097:	66 90                	xchg   %ax,%ax
38  8049099:	66 90                	xchg   %ax,%ax
39  804909b:	66 90                	xchg   %ax,%ax
40  804909d:	66 90                	xchg   %ax,%ax
41  804909f:	90                   	nop
42 
43 
44 080491b2 <print>:
45  80491b2:	55                   	push   %ebp
46  80491b3:	89 e5                	mov    %esp,%ebp
47  80491b5:	57                   	push   %edi
48  80491b6:	56                   	push   %esi
49  80491b7:	53                   	push   %ebx
50  80491b8:	e8 33 ff ff ff       	call   80490f0 <__x86.get_pc_thunk.bx>
51  80491bd:	81 c3 43 2e 00 00    	add    $0x2e43,%ebx
52  80491c3:	83 ec 0c             	sub    $0xc,%esp
53  80491c6:	8b 75 10             	mov    0x10(%ebp),%esi
54  80491c9:	8d bb 08 e0 ff ff    	lea    -0x1ff8(%ebx),%edi
55  80491cf:	3b 75 0c             	cmp    0xc(%ebp),%esi
56  80491d2:	7d 14                	jge    80491e8 <print+0x36>
57  80491d4:	50                   	push   %eax
58  80491d5:	8b 45 08             	mov    0x8(%ebp),%eax
59  80491d8:	ff 34 b0             	pushl  (%eax,%esi,4)
60  80491db:	56                   	push   %esi
61  80491dc:	46                   	inc    %esi
62  80491dd:	57                   	push   %edi
63  80491de:	e8 4d fe ff ff       	call   8049030 <printf@plt>
64  80491e3:	83 c4 10             	add    $0x10,%esp
65  80491e6:	eb e7                	jmp    80491cf <print+0x1d>
66  80491e8:	8d 65 f4             	lea    -0xc(%ebp),%esp
67  80491eb:	5b                   	pop    %ebx
68  80491ec:	5e                   	pop    %esi
69  80491ed:	5f                   	pop    %edi
70  80491ee:	5d                   	pop    %ebp
71  80491ef:	c3                   	ret    


看到這樣的結果就安心了, 真的是像文章上說的一樣, 有做 tail recursive calls Optimization。

ref:

2020年11月28日 星期六

20201111 京東購物

自從 amazon.cn 不賣實體書之後, 便找尋下一個購買簡體中文書籍的方式, 京東已經聽說很久了, 但是我一直搞不定怎麼用台灣信用卡付款。

原來是地址的問題, 只要填中國地址 (中國集運地址), 就一定強迫使用微信付款, 這我當然沒辦法使用。改用台灣地址之後, 才可以使用台灣信用付款。

在 20201111 測試一下怎麼購物, 買了 2 本書籍, 中國的 1111 折扣真的大, 台灣的實在差太多。



不但不用運費, 折購還蠻大的, 最後付了 110.10 rmb, 原價應該是 99+79 = 178 rmb。



這 2 本書都是薄薄的, 並不是很厚的那種, 定價看來是比較高的。當然, 買書不是買紙, 其技術內容很豐富。

不知道是不是 1111 運輸量太大的問題, 我直到 20201127 才收到這 2 本書。ezway 也有查到這筆訂單的訊息。

2020年11月22日 星期日

delete repos from github by bfg (DMCA takedown)

2020/11/13 收到 github 的 DMCA takedown

I'm contacting you on behalf of GitHub because we've received a DMCA takedown notice regarding the following content:

We're giving you 1 business day to make the changes identified in the following notice:

就是某個 repository 有違反版權的東西, 要你刪除或是替自己辯護。

趁這個機會了解如何真正刪除 git 上的東西。

由於 git 是版本控制, 基本上 commit 的東西就是會一直存在, 無法刪除, 所以要用很特別的方式才能「真正」刪除這些資料。

我用的是 bfg 這個工具。

java -jar ~/bfg-1.13.0.jar --no-blob-protection --delete-folders 目錄
ex: java -jar ~/bfg-1.13.0.jar --no-blob-protection --delete-folders network
java -jar ~/bfg-1.13.0.jar --no-blob-protection --delete-files 檔案
ex: java -jar ~/bfg-1.13.0.jar --no-blob-protection --delete-folders a.txt
然後在執行以下 git 指令
git reflog expire --expire=now --all && git gc --prune=now --aggressive

很複雜吧, 我自己也不知道在幹嘛, 不過還沒完 ...

push 回去
git push
如果遇到錯誤訊息, 改用以下指令
git push origin --force --all

這樣在 github 上的東西就真的刪除了。

一般來說我們很少會需要這種操作, 通常是用在不小心把帳號/密碼之類的檔案 commit 進去, 才會需要用到這招。

然後在回信給 github 說已經刪除相關有問題的檔案, 如果沒有做任何處理, 一天之後, 這個 repository 會被封鎖。

We're giving you 1 business day to make the changes identified in the following notice:

我對這句話很不爽, 就算我英文不好, 也能感受到滿滿不舒服, 而且只給一天。

以後會以 bitbucket 為主, 新的程式碼會優先放在 bitbucket。

ref:
bfg: