C++中使用new分配指针后执行delete触发断点,如何正确删除指针?
报错根因
触发程序断点的直接原因是调试版C运行时(CRT)检测到堆内存重复释放,也就是你对同一块通过new申请的堆内存执行了两次释放操作,CRT的内存校验逻辑会直接中断程序触发断点。
你代码中连续出现3个典型的指针操作错误,共同导致了这个问题:
- 构造函数中的指针覆盖造成内存泄漏
构造函数内的代码逻辑:
第一行通过a = new double; a = x;new申请了一块double大小的堆内存,把地址存入指针a;第二行直接将a的值覆盖为外部传入的x的地址,最开始new出来的那块内存从此没有任何有效指针指向,永远无法被释放,形成永久内存泄漏。b、c指针的处理逻辑和a完全一致,存在同样的问题。 delete语句中的逗号表达式语义陷阱
你写的所有类似delete a, b, c;的代码,本质是C++的逗号操作符:整个表达式会从左到右依次执行每个子表达式,但只有最后一个子表达式的结果会作为整个语句的返回值。
这类语句的实际执行逻辑是:- 对a指向的内存执行delete
- 取出b的值(不执行任何内存操作)
- 取出c的值(不执行任何内存操作)
整个语句根本不会对b、c指向的内存执行释放操作。
- 跨作用域的内存重复释放
main函数中通过new申请了j、k、l三块堆内存,将其地址传入类对象后,类的析构函数会对a(即j的地址)执行一次delete;但main函数末尾又对j的地址执行了一次delete——同一块堆内存被连续释放两次,直接触发CRT的断点校验。
修复方案
- 明确内存所有权:动态申请的堆内存必须由唯一的主体负责释放,禁止跨作用域对同一块内存执行delete操作。
- 修正构造函数逻辑:如果类需要自主管理内存,就需要在
new申请空间后,把外部传入的值拷贝到申请的内存中,不能直接覆盖指针指向的外部地址:userValue::userValue(double *x, double *y, double *z) { discrim = 0; a = new double(*x); // 申请内存后拷贝对应值,不直接存外部指针地址 b = new double(*y); c = new double(*z); } - 修正所有delete语句的写法:每个指针的释放操作单独编写,禁止用逗号拼接多个delete目标:
userValue::~userValue() { delete a; delete b; delete c; } - 如果选择由main函数负责管理所有内存,那么类的析构函数绝对不能执行delete操作,仅保留指针指向的地址用于运算,所有内存释放逻辑全部放在main函数中,同样需要逐个执行delete操作。
- 场景优化:对于这个二次方程求解的场景,完全不需要使用指针,类成员直接存储double类型的数值即可,从根源上规避动态内存操作的各类风险。
内容的提问来源于stack exchange,提问作者Joel Gray
相关产品推荐
相关产品推荐

