VC++下一個看似簡單實則頗有「內涵」的C/C++字符數組初始化問題

學過C/C++的親想必也知道,C類型字符數組(數組存儲的字符串)初始化問題在譚浩強(其實我真不想說此人……)那本「萬年不爛」的C語言入門書籍上是這樣給予說明的算法

char c[] = "hello world";數組

或者安全

char c[] = {'h','e','l','l','o',' ','w','o','r','l','d',NULL};測試

儘管在對字符數組的初始化問題上,二者所達到的功效是同樣的,或者說前者看上去會更友好,因此估計大部分人也就一直是使用前一種初始化方式,而不只是譚浩強的書,市面上大部分有關C語言的書籍也並無給出兩種方法的實如今不一樣環境下到底有什麼差別,因此想必大部分人也沒有其深究這個問題。優化

然而,在不一樣平臺不一樣編譯器環境上,兩種實現方式對字符數組的初始化在過程上仍是有很大差別的,緣何如此說?那麼如今就給你們從彙編的角度,來看看這二者到底有什麼差別。編碼

如今咱們初始化兩個C字符數組spa

char c[] = {'h','e','l','l','o',' ','w','o','r','l','d',0};ci

char a[] = "hello world";開發

接下來看看反彙編字符串

VS下O2優化

GCC下O2優化(Win下的IDA視圖)

(Mac環境下但願有小夥伴能夠提供看看)

從反彙編上看,VC++上的差別是明顯的。在VS實現字符數組的初始化中,前者(字符數組c)是以"mov 存儲單元,對應字符的ascii碼"的形式來對每個數組元素進行賦值,然後者則是直接將某個數據地址以每次4字節的形式先拷貝到通用寄存器中,再經過其中轉來賦給字符數組a的每個元素。而GCC上,二者都在數據段留下了副本,而並無同VS那樣硬編碼到代碼段。

這個不起眼的初始化問題在應用開發上確實沒有什麼大的差異,可是在VC++的開發中,這兩種不一樣的賦值方式倒是十分值得相關人員注意的,爲何這樣說?從前面內容可知,後者會將初始化內容在數據段留下一個「副本」,因而經過這段「副本」,對於喜歡搞「爆破」的人來講,就至關於給他們開了一個捷徑,使其迅速找到了軟件的"爆破點",對於那些使用內部算法來實現註冊可是卻未加殼的軟件來講,破解真的就是分分秒秒的事情.因此說,後者的賦值你說是否是至關於告訴了那些破解者們"我在哪裏幹了什麼"?

而前者的賦值方式,因爲相應的初始值是被硬編碼到可執行代碼段的,因此必定程度上來講是有必定隱藏做用的。

另感謝@bigtan 指出錯誤,因此從新修改了本文的觀點,因爲剛剛入安全這一行,各類觀點還欠缺成熟的考慮,還望你們在往後多多指出本人的錯誤

(PS:本文中的VC++版本均已作了從VC6至現今版本的測試)

相關文章
相關標籤/搜索