为什么未调整大小的C++动态数组仍可正常运行?
C++动态数组越界访问看似正常的原因
C++语言标准本身没有为原生数组(包括堆上分配的动态数组)设计强制边界检查机制,这是出于极致性能的设计取舍,越界访问属于未定义行为,你遇到的运行正常只是未定义行为的一种表现,不代表代码是合法的。
具体行为解释
- 你调用
new T[n]分配内存时,操作系统只会保证起始地址开始、长度为sizeof(T)*n的内存段是合法分配给当前进程的可用空间,返回的指针仅记录起始地址,不存储数组长度信息。 - 当你访问
myDynamicArr[i]时,本质只是做起始地址 + i * sizeof(元素类型)的地址偏移,只要偏移后的地址属于当前进程有权限读写的内存页,就不会触发操作系统的内存访问错误(段错误),读写操作都可以正常执行。 - 你用到的
strcpy同样没有缓冲区边界检查逻辑,只要目标地址后续内存可写,就会一直将源字符串的内容逐个拷贝,直到遇到结束符\0,所以能正常输出长字符串只是凑巧后续内存可用,没有触发访问异常。
潜在风险
这种越界访问的代码存在极高的安全隐患:
- 可能覆盖堆上其他已分配对象的内存数据,导致程序逻辑莫名出错,且极难排查
- 一旦访问到进程无权限的内存页,会直接触发段错误,程序异常终止
- 存在缓冲区溢出漏洞,极端情况下可被恶意构造的输入利用,执行任意代码
推荐实践
- 尽量使用C++标准库容器
std::vector替代原生动态数组,其at()成员方法会主动做边界检查,越界时会抛出异常便于定位问题 - 处理字符串优先使用
std::string,避免手动管理char数组和使用strcpy这类无边界检查的不安全函数 - 如果必须使用原生数组,建议自行添加边界校验逻辑,避免越界访问
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

