异常处理是否可用于避免坏指针触发的程序崩溃问题?
可行性判断
从Windows平台的技术实现角度看,这种做法可行:
- Windows下用户态内存访问违规对应的异常码是
STATUS_ACCESS_VIOLATION,你可以用Windows结构化异常处理(SEH)的__try/__except块捕获,或是给C++编译器开启/EHa选项(支持异步异常捕获)后用标准try/catch块捕获,确实可以避免程序直接崩溃。
为什么属于不推荐的不良实践
- 存在**TOCTOU(检查与使用时间差)**风险:
VirtualQuery校验和异常捕获都不是原子操作,只要校验和实际访问存在时间差,中间就可能出现内存页属性被其他线程修改的情况(比如校验完成后、实际访问前对应页刚好被释放),两种方案都做不到100%可靠。 - 性能开销极高:Windows触发异常需要完成内核态/用户态切换、异常上下文遍历、栈展开等一系列操作,单次异常触发的耗时是
VirtualQuery调用的数百上千倍,高频场景下会严重拖累程序性能。 - 会掩盖程序本身的逻辑错误:指针非法本质上大概率是程序自身存在BUG,比如野指针、内存越界、提前释放资源等,靠捕获异常跳过错误会让本应在开发阶段暴露的问题被隐藏,后期排查难度会大幅提升。
- 可移植性极差:这类依赖Windows平台异常机制捕获内存错误的逻辑,完全无法迁移到Linux、MacOS等其他系统,后续有跨平台需求时需要全部重写。
- 存在安全隐患:如果程序对外暴露可输入接口,恶意攻击者可以构造特殊输入触发大量访问异常,轻则导致程序性能骤降,重则可能利用异常处理逻辑漏洞实现越权操作或代码执行。
更合理的实践建议
- 仅在临时调试场景下可以用异常捕获的方式定位问题,不要在生产环境上线这类兜底逻辑。
- 优先从根源解决指针非法问题:比如用智能指针管理内存、增加访问边界校验、从逻辑上避免野指针生成,而不是靠事后校验或异常捕获兜底。
- 如果确实需要处理不可信的外部输入指针(比如第三方模块传入的指针),可以用
VirtualQuery前置校验+访问时加SEH兜底的双重方案,安全性比单独使用异常捕获高很多。
内容的提问来源于stack exchange,提问作者DevilMan
相关产品推荐
相关产品推荐

