【问题标题】:Segmentation fault when using Used-defined conversion operator使用已用定义的转换运算符时出现分段错误
【发布时间】:2019-10-01 19:43:24
【问题描述】:

我已经实现了下面这段代码

#include <iostream>
#include <memory>

class A
{
    public:
        int a;

        virtual ~A()
        {
        }
};

class B : public A
{
    public:
        int b;

        virtual ~B()
        {
        }
};

class E : public B
{
    public:
        ~E()
        {
        }
};

class D
{
public:
    operator std::shared_ptr<A>()
    {
        std::shared_ptr<A> pa = std::make_shared<A>();
        pa->a = this->y;
        return pa;
    }

    operator std::shared_ptr<B>()
    {
        std::shared_ptr<A> pb = std::make_shared<B>();

        pb = *this;
        (std::static_pointer_cast<B>(pb))->b = this->x;
        return std::static_pointer_cast<B>(pb);
    }

    virtual ~D()
    {
    }

    int x;
    int y;
};

int main()
{
    D d;
    d.x = 6;
    d.y = 7;
    std::shared_ptr<E> pE = std::make_shared<E>();
    std::shared_ptr<A> pa = pE;

    std::shared_ptr<B> pB = std::dynamic_pointer_cast<B>(pa);
    pB = d;
    std::cout << "a " << pB->a << "b " << pB->b << std::endl;
    return 0;
}

我尝试做的是将类Dd 的实例转换为派生自类A 的共享指针B 的实例。

B 继承类AE 继承类B

程序终止时,程序在A类的析构函数中崩溃。

我使用 GDB 发现 this 为 NULL。

有人知道为什么会这样吗?

【问题讨论】:

  • 进行以下更改 (std::dynamic_pointer_cast(pb))->b = this->x;返回 std::dynamic_pointer_cast(pb);程序在 this->x 的分配中崩溃。 pb 为 NULL。
  • 没错。这告诉您您正在以无效的方式访问pb,因为它没有指向有效的B 对象,因此您不能将A 指针转换为B 指针。您需要修复您的 operator std::shared_ptr&lt;B&gt;() 才能对有效的 B 对象进行操作。

标签: c++ operators


【解决方案1】:

D::operator std::shared_ptr&lt;B&gt;()内部,std::static_pointer_cast&lt;B&gt;(pb)的使用是未定义的行为,因为pb此时并没有指向B的实例,所以强制转换是非法的A 指向 B 指针并访问 B 的成员。 pb 指向std::make_shared&lt;A&gt;()D::operator std::shared_ptr&lt;A&gt;() 中创建的A 实例。在语句pb = *this; 中,您将丢弃您创建的B 对象并获得*this 返回的A 对象的所有权。

因此,在main() 内部,pB 最终指向一个无效的B 对象,并在main() 退出时尝试破坏该对象,这就是您最终导致A 析构函数崩溃的原因。

如果您在D::operator std::shared_ptr&lt;B&gt;() 内部使用dynamic_pointer_cast 而不是static_pointer_cast,那么您最终会得到一个NULL 指针,并且在访问B::b 时可能会在D::operator std::shared_ptr&lt;B&gt;() 内部崩溃,而不是在main() 中崩溃.

您需要修复您的operator std::shared_ptr&lt;B&gt;() 才能在B 的有效实例上运行,而不是在A 的实例上运行。例如:

operator std::shared_ptr<B>()
{
    std::shared_ptr<B> pb = std::make_shared<B>();
    std::shared_ptr<A> pa = *this;

    *static_pointer_cast<A>(pb) = *pa; // <-- copy pa->a to pb->a ...
    // or: simply do this instead:
    // pb->a = pa->a;

    pb->b = this->x;
    return pb;
}

【讨论】:

    猜你喜欢
    • 2019-06-09
    • 2010-12-30
    • 1970-01-01
    • 2018-09-10
    • 2013-04-07
    • 2020-12-11
    • 2017-12-26
    • 2015-05-01
    • 2015-11-20
    相关资源
    最近更新 更多