You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++传递对象引用时类成员指针失效触发SIGSEGV问题求助

问题分析与解决思路

咱们先把这个SIGSEGV错误的根源揪出来——悬挂指针(Dangling Pointer),结合你的代码细节,问题出在这几个核心点上:

1. 第二个构造函数的设计缺陷

你的第二个构造函数直接保存了传入Poly对象的地址:

rat::rat(Poly &p1, Poly &p2) : p1(&p1), p2(&p2) { }

如果传入的Poly是临时对象(比如r1*r1+r2这类表达式里生成的临时Poly实例),这些临时对象会在当前表达式执行完后立刻被销毁。这时候你的rat对象里的p1、p2就指向了已经被释放的内存,后续访问(比如operator<<里的解引用操作)自然会触发段错误,你看到的乱码d值就是内存被覆写后的垃圾数据。

2. 忽略了拷贝构造函数的作用

你提到执行rat r = r1*r1+r2;时出问题,这里要注意:=在这里是拷贝构造,不是你写的赋值运算符!编译器会生成默认的拷贝构造函数,默认行为是浅拷贝——直接复制指针值。如果r1*r1+r2返回的是临时rat对象,当这个临时对象销毁时,它持有的p1、p2指向的内存会被释放(假设Poly有正确的析构函数),而r里的指针就会变成悬空指针,后续访问必然出错。你写的赋值运算符根本没被调用,所以解决不了问题。

3. const成员d的误导

你说r.p1->d是const,这只是意味着你无法修改它,但如果指针指向的内存已经失效,即使是const成员也会读取到垃圾值,这和const本身无关,根源还是指针悬空。


具体解决步骤

步骤1:重构构造函数,改用深拷贝

把第二个构造函数改成深拷贝传入的Poly对象,而不是直接保存外部对象的指针,这样你的rat会拥有独立的Poly实例,不再依赖外部对象的生命周期:

rat::rat(const Poly &p1, const Poly &p2) : p1(new Poly(p1)), p2(new Poly(p2)) { }

步骤2:手动实现拷贝构造函数和析构函数

必须自己写拷贝构造函数(深拷贝)和析构函数,避免编译器生成的默认浅拷贝带来的问题:

// 析构函数:释放p1和p2指向的内存,避免内存泄漏
rat::~rat() {
    delete p1;
    delete p2;
}

// 拷贝构造函数:深拷贝传入对象的Poly实例
rat::rat(const rat &other) : p1(new Poly(*other.p1)), p2(new Poly(*other.p2)) { }

步骤3:完善赋值运算符(用拷贝交换 idiom)

你之前写的赋值运算符可以优化成更安全的拷贝交换方式,避免异常安全问题:

rat& rat::operator=(rat other) { // 传值时自动触发拷贝构造
    std::swap(p1, other.p1);
    std::swap(p2, other.p2);
    return *this;
}

这样当other离开作用域时,原来的p1、p2会被它的析构函数自动释放,既安全又简洁。

步骤4:修改友元operator<<为const引用

打印操作不应该修改rat对象,所以把参数改成const引用,同时确保Poly的operator<<也支持const对象:

ostream &operator<<(ostream &stream, const rat &r) {
    return stream << *(r.p1) << "--------------------------" << std::endl << *(r.p2);
}

额外排查点

如果做完以上步骤还是有问题,建议检查:

  • Poly类的析构函数是否正确释放了自己的资源(比如动态分配的数组),避免内存泄漏或二次释放。
  • Poly的拷贝构造函数是否正确实现了深拷贝,如果Poly本身有动态成员,浅拷贝会导致同样的悬空问题。

内容的提问来源于stack exchange,提问作者Ben Yaakobi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 14:52:33