使用 Used-defined 转换运算符时出现分段错误
Segmentation fault when using Used-defined conversion operator
我已经实现了下面的一段代码
#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;
}
我尝试做的是将 class D
、d
的实例转换为从 [= 派生的共享指针 B
的实例33=] A
.
B
继承classA
,E
继承classB
。
当程序终止时,程序在classA
的析构函数中崩溃。
我使用了 GDB,发现 this
是 NULL。
有人知道为什么会这样吗?
在D::operator std::shared_ptr<B>()
内部,std::static_pointer_cast<B>(pb)
的使用是未定义的行为,因为pb
没有指向[=的实例14=],所以将 A
指针转换为 B
指针并访问 B
的成员是非法的。 pb
指向 std::make_shared<A>()
在 D::operator std::shared_ptr<A>()
中创建的 A
实例。在语句 pb = *this;
中,您正在丢弃您创建的 B
对象并获得 *this
returns.
的 A
对象的所有权
因此,在 main()
内部,pB
最终指向无效的 B
对象,并在 main()
退出时尝试破坏该对象,这就是为什么你最终导致 A
析构函数崩溃。
如果您在 D::operator std::shared_ptr<B>()
中使用 dynamic_pointer_cast
而不是 static_pointer_cast
,您最终会得到一个 NULL 指针,并且在访问 [时可能会在 D::operator std::shared_ptr<B>()
中崩溃=35=],而不是在 main()
.
中崩溃
您需要修复 operator std::shared_ptr<B>()
以在 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;
}
我已经实现了下面的一段代码
#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;
}
我尝试做的是将 class D
、d
的实例转换为从 [= 派生的共享指针 B
的实例33=] A
.
B
继承classA
,E
继承classB
。
当程序终止时,程序在classA
的析构函数中崩溃。
我使用了 GDB,发现 this
是 NULL。
有人知道为什么会这样吗?
在D::operator std::shared_ptr<B>()
内部,std::static_pointer_cast<B>(pb)
的使用是未定义的行为,因为pb
没有指向[=的实例14=],所以将 A
指针转换为 B
指针并访问 B
的成员是非法的。 pb
指向 std::make_shared<A>()
在 D::operator std::shared_ptr<A>()
中创建的 A
实例。在语句 pb = *this;
中,您正在丢弃您创建的 B
对象并获得 *this
returns.
A
对象的所有权
因此,在 main()
内部,pB
最终指向无效的 B
对象,并在 main()
退出时尝试破坏该对象,这就是为什么你最终导致 A
析构函数崩溃。
如果您在 D::operator std::shared_ptr<B>()
中使用 dynamic_pointer_cast
而不是 static_pointer_cast
,您最终会得到一个 NULL 指针,并且在访问 [时可能会在 D::operator std::shared_ptr<B>()
中崩溃=35=],而不是在 main()
.
您需要修复 operator std::shared_ptr<B>()
以在 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;
}