C++固定大小数组为何可写入越界元素且部分场景无报错?
C++ 数组越界异常现象原因分析
你遇到的现象本质是C++ 原生数组越界访问属于未定义行为,C++标准没有对这类操作的结果做任何约束,程序出现崩溃、正常运行、输出异常结果等任何表现都是符合规范的。
具体到你遇到的不同表现,原因如下:
- 访问
mynum[3]触发崩溃,是当前编译器开启了栈金丝雀(Stack Canary)保护机制导致的:
现在主流的GCC、MSVC编译器默认都会在函数栈帧的数组缓冲区和栈返回地址之间插入一个固定的校验值。你声明的int mynum[3]共占用12字节内存(单int占4字节的前提下),mynum[3]的地址刚好对应这个校验值的存储位置,你对该位置赋值4直接篡改了校验值,函数执行结束前编译器会校验该值,发现被篡改就会直接抛出stack smashing detected错误终止程序。 - 访问
mynum[4]、mynum[5]、mynum[6]未触发报错属于巧合:
这些地址已经越过了栈金丝雀的存储位置,踩中的是栈上其他无关内存区域,可能是编译器预留的栈对齐空白空间,也可能是函数内已经不会被访问的临时变量内存,只要没有覆盖到栈帧返回地址、也没有触发内存访问权限异常,程序就会暂时表现为“正常运行”。但这类代码始终存在严重安全隐患,只要编译参数、运行环境发生变化,随时可能出现崩溃、数据污染等问题。
注意:生产环境中禁止依赖未定义行为的表现,需要可变长度的序列时优先使用
std::vector代替原生固定数组,可大幅降低越界风险。
内容的提问来源于stack exchange,提问作者Sidharth Tripathi
相关产品推荐
相关产品推荐

