C++中std::cin超长输入致相邻int变量数据损坏问题排查
代码示例
#include<iostream> // 原代码缺省strtol对应的头文件,实际编译需引入#include <cstdlib> int main() { int a=3; char ch[5]; std::cout<<&a<<"\n"<<(void*)(ch)<<"\n"; long int k1=strtol("0x70fe14",nullptr,16); // 7405076 long int k2=strtol("0x70fe00",nullptr,16); // 7405056 std::cout<<k1<<"\n"<<k2<<"\n"; std::cout<<a<<"\n"; std::cin>>ch; std::cout<<a<<"\n"; std::cout<<ch<<"\n"; }
运行输出
0x70fe14 0x70fe00 7405076 7405056 3 12345678912345678912 // 此处为给std::cin>>ch输入的内容 0 12345678912345678912
问题原因
这是典型的栈缓冲区溢出问题:
- 你定义的
ch是长度为5的char数组,仅能容纳4个有效字符+1个字符串结束符\0,总共5字节内容。std::cin >>读取C风格字符串时默认不会做输入长度校验,你输入了20个字符,远超过数组可承载的上限,超出的内容会直接写入ch数组边界外的内存空间。 - 多数编译器的栈内存是从高地址向低地址分配的,先声明的变量
a被分配在更高的内存地址(起始地址7405076),后声明的ch数组被分配在更低的地址(范围7405056~7405075)。当ch的写入溢出时,刚好会覆盖相邻高地址处a的内存空间,导致a原本存储的数值3被篡改,就出现了你看到的输出为0的情况。
修复建议
- 优先使用
std::string接收字符串输入,会自动管理内存边界,不会出现溢出问题。 - 如果必须使用C风格char数组,需要指定读取的最大长度,例如使用
std::cin >> std::setw(5) >> ch,需提前引入<iomanip>头文件。
内容的提问来源于stack exchange,提问作者Forrest Gump
相关产品推荐
相关产品推荐

