溢出字符数组每次都覆盖完全相同的字符串-为什么?
Overflowing char array overwrites the exact same string every time - why?
下面的代码显示了在字符串上使用字符数组的危险:
int main(){
char password[] = "SECRET";
char msg[10], ch;
int i = 0;
cout << "Please enter your name:";
while((ch = getchar()) != 'n'){
msg[i++] = ch;
}
msg[i] = ' ';
cout << "nnHello " << msg << endl;
cout << "The password is " << password;
}
当我输入的名称(存储在char msg[10]
中)大于16个字符时,这16个字符之后的内容将替换存储在char password[]
("SECRET")中的值。
- 为什么会这样?(一般的好奇心)
- 为什么16个字符而不是10 -数组的大小?
- 为什么总是
password
被覆盖,而不是其他变量或内存的其他部分,我不会立即注意到? - 使用char[]比字符串有什么好处呢?
编辑:更新了后续问题:
5。针对password
和msg
相邻声明的论点,我将声明块洗牌如下:
char password[] = "SECRET";
char ch;
int i = 0;
char msg[10];
然而,没有变化。
6。作为对导致msg
和password
之间的差距为6(字节?)长的争论的回应,我已经多次重新编译了代码,包括上面的重组。但还是没有变化。
有什么建议吗?
前三个问题的答案是相同的:因为这是编译器选择在堆栈上布局这些变量的方式。标准中没有任何内容保证——事实上,你所做的是未定义的行为——任何事情都可能发生。
改变编译器,甚至是编译器设置,还有其他可能发生的事情。与否。说不准。
对于4,除了与C代码的互操作性,或者其他需要C风格字符串的api,基本上没有。
1。在您的情况下,内存是这样存储的:
msg | |i |password
| | | | | | | | | | |1|2|3|4|5|6|S|E|C|R|E|T|
然后在msg上依次写:
msg | |password
|A|Z|E|R|T|Y|U|I|O|P|1|2|3|4|5|6|S|E|C|R|E|T|
但是如果你继续:
msg | |password
|A|Z|E|R|T|Y|U|I|O|P|1|2|3|4|5|6|Q|W|E|R|T|Y|
因为char数组不检查长度。(搜索溢出).
你在内存上写东西,你擦除其中的所有东西,可能是i或不属于你的程序的东西。
3,所以在覆盖密码之前需要6个字符。可以是0char,也可以是millions。
4 .除非你存储一个定义好的字节数组…什么也没有,这是代码所证明的。
更新:改变代码的位置不会改变填充,添加变量,数组,或者更好:使用不同的编译器,这样即使优化后,二进制文件也会改变。
重新编译不会改变生成的二进制文件,因为编译器会做完全相同的事情。
您的两个数组msg
和password
是静态的,因此它们被放置在堆栈上,这意味着它们彼此靠近。
细节依赖于实现,并且可能在编译器和优化级别之间发生变化。有可能编译器在分配内存时填充了堆栈,msg[0]
和password[0]
之间有16个字节的间隙。
password
每次都会被覆盖,因为它恰好在堆栈中的msg
之上。如果您使用不同的编译器,或者在代码中交换了它们的位置,则可能不会。在执行之间,堆栈上的东西分配方式不会改变;它是在编译时确定的(它是静态的),而不是运行时。
注意,原则上,编译器可以自由地做任何它想做的事情!对于典型的编译器行为,我们只能做出有根据的猜测。如果您真的想知道发生了什么,您必须查看输出程序集。
std::string
(对于c++)通常比char[]
更可取,因为它实现了绑定检查并管理自己的内存,因此要安全得多。
1)在数组外写入将访问其他内容。
2)可能对齐。
3)机会。一切皆有可能。
4)任何东西!
- 为什么 sscanf 无法从一个字符串中读取uint64_t和字符?
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 为什么这个 c++ 代码打印出长度 5,当我打印出字符串时,程序会自动终止?
- C ++中的StringStream有助于使用向量从字符串中提取逗号分隔的整数,而不是空格分隔的整数,为什么?
- 为什么我不能将字符串::赋回字符串?
- 为什么字符串比较的 == 运算符相对于任一字符串长度线性时间(似乎)?
- 为什么字符串的 move() 会改变内存中底层数据的位置?
- 为什么我的字符串变量没有打印完整的字符串?
- 为什么我的子类不继承父类的字符串?
- C++字符串大小减去整数不是预期值,为什么?
- 为什么我的 cout 在输出中没有显示字符串?
- 为什么在为其分配编号后无法显示我的字符串值?
- 为什么没有访问所有字符串字符?
- 为什么可以将整数分配给字符串变量?
- C++子字符串为什么这样做
- 我的课堂上不能有字符串.为什么
- C++字符串为什么不能用作字符数组
- C++字符串流:接受字符串,但不接受存储在变量中的字符串.为什么?
- 反向字符串:为什么会崩溃
- 溢出字符数组每次都覆盖完全相同的字符串-为什么?