指针(2)指针常见问题(re迭代)

本文详细解析了C++编程中常见的内存问题,包括缓冲区溢出、空悬指针/野指针、重复释放、内存泄露等,并提供了有效的解决方案,如使用智能指针(如shared_ptr、weak_ptr)来避免空悬指针和野指针问题,以及如何正确处理重复释放和内存泄露。此外,文章还讨论了内存分配的位置,包括静态存储区、堆栈和堆,并强调了初始化指针的重要性以及如何预防指针操作错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

what 空悬指针(dangling pointer):指向已经销毁的对象或已回收的地址(《Linux多线程服务端编程》p7)
what 野指针(wild pointer):未经初始化的指针

《Linux多线程服务端编程》p15
which 内存问题(C++里可能出现的内存问题
1)缓冲区溢出(buffer overrun)
2)空悬指针/野指针
3)重复释放(double delete)
4)内存泄露(memory leak)
5)不配对的new[]/delete
6)内存碎片(memory fragmentation)
7)父类指针delete子类对象,而该父类的析构函数是non-virtual。结果未定义,实际执行时通常发生的是,对象的子类部分没被销毁(《effective c++ 》p71 item7) 
how对策
1)空悬指针/野指针 用shared_ptr/weak_ptr
2)重复释放 用scoped_ptr,只在对象析构的时候释放一次

when 空悬指针/野指针 【!造成后果非法访问】(《高质量程序设计指南c语言(第三版)林锐》 p310)
1)没有初始化指针变量【how对策:1)定义立即初始化 2)不要忘记初始化指针,数组,动态内存】
2)指针变量被free()或者delete之后,没有置为NULL【how对策:delete或free()之后,立即置为NULL;即便delete之后立即用new赋新值,也要先在delete之后赋NULL,因为考虑到异常安全的问题,见《effective c++》Item29(或者更好的是,先new再delete,new之后指针交换再delete)。】
3)指针操作超越了变量的作用范围 【how对策:不要让指针指向堆栈变量;要指向堆栈变量,也要保证定义和使用都在一个作用域;如果定义在作用域外,也要在一出作用域的范围外,置为NULL】
4)函数return返回“堆栈内存”(即,局部对象)的指针或引用.若返回的局部对象为static则可以,参考singleton模式
5)数组越界和指针越界(比如用指针进行算术操作时)(特别是在循环中)

when 内存泄露 (《高质量程序设计指南c语言(第三版)林锐》p305)
1.忘记了释放内存,或只释放了部分内存(a)new []内存却delete而没有delete[]   b)比如你使用了错误的动态数组释放语法)
2.指针变量赋值操作:指针变量未delete或free()之后,又赋新值
3.控制流提前跳过delete语句:意外修改造成的问题,有几种可能性(参考智能指针的引入)
4.类类型对象在构造函数中抛出异常,而构造函数中在抛出异常的语句之前有分配过资源(包括内存)

where 内存分配位置
1)静态存储区(static memory):《c++ primer英文版 第5版》p562  《高质量程序设计指南c语言(第三版)林锐》p304
局部静态变量,类静态成员变量,函数外定义的变量(gloable作用域,file作用域,namespace作用域)
2)堆栈(statck memory)
3)堆(即自由存储区 heap or free store)

### 关于洛谷平台上RE错误的原因及解决方案 #### 错误定义 运行时错误(Runtime Error, RE)是指程序在执行过程中遇到了无法处理的情况,导致程序崩溃或终止。这种错误可能由多种因素引起。 --- #### 可能原因分析及其解决办法 1. **数组越界** 数组访问超出其分配的内存范围是最常见的原因之一[^3]。这可能导致不可预测的行为甚至程序崩溃。 - **解决方法**: 阅读题目中的数据范围说明,合理设置数组大小。如果不确定具体数值,可适当增加冗余空间以降低风险。例如: ```cpp int n; cin >> n; vector<int> arr(n + 10); // 多预留一些空间以防万一 ``` 2. **指针操作不当** 如果涉及动态内存管理(如`new`/`delete`),未正确释放资源或将非法地址赋给指针也可能引发RE。 - **解决方法**: 使用现代C++特性(如`std::vector`, `std::unique_ptr`等容器类替代原始指针)。确保每次申请内存后都及时清理不再使用的部分。 3. **除零异常** 当尝试将某个数除以零时会触发此类型的错误。 - **解决方法**: 提前判断分母是否为零再决定如何计算表达式的值。 ```cpp double a = ..., b = ...; if (b != 0){ cout << a / b; }else{ cout << "Error"; } ``` 4. **类型转换失误** 特定情况下某些内置函数对特定的数据类型支持有限制。比如标准库里的`abs()`只适用于较小整型;当遇到更大规模数字则需改用其他版本如`llabs()`针对长整形[^5]。 - **解决方法**: 明确所需运算对象的确切类别并调用相应的适配器完成任务。 5. **栈溢出** 过深递归层次可能会耗尽系统允许的最大堆栈容量从而造成失败退出状况发生。 - **解决方法**: 考虑优化算法结构减少不必要的嵌套层数或者切换至迭代形式实现相同功能逻辑。 6. **输入输出格式不符预期** 不按照指定方式获取外部参数亦或是打印结果不符合规定样式同样会被判定存在此类问题。 - **解决方法**: 细致审阅样例测试案例以及提示信息严格遵照指示编写相应代码片段。 7. **第三方依赖缺失** 若项目里引入额外库文件却忘记上传关联源码到评测环境当中也有可能遭遇相似困境。 - **解决方法**: 尽量采用官方文档推荐的基础组件构建应用避免过多自定义扩展带来的兼容隐患。 8. **边界条件遗漏考虑** 对极端情况缺乏足够的重视往往成为隐藏漏洞所在之处之一。 - **解决方法**: 设计全面覆盖各类可能性场景单元检验机制验证最终成品质量。 --- ### 总结建议 为了有效预防上述提及的各种潜在陷阱,在日常练习期间应当养成良好习惯如下几点可供参考借鉴: - 认真阅读每一道习题描述材料充分理解需求背景; - 结合实际动手实践不断积累实战经验提升技术水平; - 定期回顾总结过往经历找出薄弱环节加以改进完善; - 积极参与社区交流学习他人优秀做法共同进步成长。 通过持续努力相信能够逐步克服目前面临的困难局面取得理想成绩! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值