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至现今版本的测试)

相关文章
相关标签/搜索