C++:即使转换的对象不是 NULL,dynamic_cast 也会导致 SEGFAULT。怎么会这样?

Posted

技术标签:

【中文标题】C++:即使转换的对象不是 NULL,dynamic_cast 也会导致 SEGFAULT。怎么会这样?【英文标题】:C++: dynamic_cast causes a SEGFAULT even when the object that is casted is not NULL. How can that happen? 【发布时间】:2013-01-09 18:20:58 【问题描述】:

假设我有一个类 A 和一个从 A 派生的类 B。现在,我想使用 dynamic_cast 将一个 const A*(称为“a”)转换为 B*(见下文)。如果“a”真的是 B*,那么我得到的对象指针应该没问题。如果“a”不是 B*,那么我将得到 NULL。

const A* a = new B();
const B* b = dynamic_cast<const B*>(a);

由于某种原因,dynamic_cast 操作会导致 SEGFAULT。如果“a”不为空,怎么会发生这种情况?我猜如果有任何转换问题,dynamic_cast 会给我一个 NULL 指针,而不是 SEGFAULT。如果我试图访问“b”并且动态转换不成功,我应该只获得 SEGFAULT,对吧?我什至还没有尝试访问“b”。

那么,这怎么会发生呢?上面的代码中是否有任何我不知道的可能导致 dynamic_cast 到 SEGFAULT 的内容?

提前致谢:-)

编辑:通过 GDB 运行我的实际程序会给出以下输出:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) where
#0  0x0000000000000000 in ?? ()
#1  0x00007ffff6c0e612 in __cxxabiv1::__dynamic_cast (src_ptr=<optimized out>, 
src_type=0x4fa6b0, dst_type=0x516bb0, src2dst=0)
at /var/tmp/portage/sys-devel/gcc-4.6.3/work/gcc-4.6.3/libstdc++-v3/libsupc++/dyncast.cc:61

输出中的下一行只是指向我的代码中我进行动态转换的行。

【问题讨论】:

问题出在AB 的定义中——只要有适当的定义,你的代码就可以工作。因此,发布一个最小的、完整的代码 由于您的示例代码显然不是您的真实代码,您是否使用dynamic_cast 来获取引用类型而不是指针类型?在这种情况下,将引发异常。见这里:ideone.com/uugF37 不要向我们“假设”代码,编写最小的、可编译的测试代码并展示我们。否则,您是在要求我们使用精神力量来修复您的代码。 【参考方案1】:

使用 dynamic_cast 时可能导致崩溃的原因

指针指向一个空闲内存块。 指针指向非多态类型。 指针指向具有多态类型但存在于禁用 RTTI 编译的外部库中的对象。 指针指向可能导致保护异常的内存访问(例如保护页或不可访问页)。

验证其中一种情况是否适用于您。

【讨论】:

另一种可能性是在共享库中声明了一种类型,而编译器是 g++。例如:***.com/questions/2351786/… 谢谢。我不使用外部库(仅 wxWidgets,但失败的代码不会“触摸” wxWidgets 对象或类似的东西)。在我的程序中,A 类是一个具有严格虚拟方法的抽象类(声明后=0)。 A 中的析构函数被声明为“virtual ~A() ”。 GDB 输出(见编辑)对于判断可能出现的问题是否有用?谢谢。 @pvh1987:在我看来它是一个 NULL 指针异常【参考方案2】:

对于像我这样的其他人,你可能不小心给了投射对象与你投射它的对象相同的变量名!

A *name = new B();
B *name = dynamic_cast<B*>(name);

对于如此明显的代码,显然是错误的,但是由于变量分散且演员表被混淆,这样的错误在野外可能更难发现!

【讨论】:

这在语法上无效,我什至不知道你是如何通过编译器的 @searchengine27 如果第一个变量是在其他范围内声明的,例如类成员变量,它会编译。就像我说的,这是一个真正的周五深夜错误,但会导致提问者提到的相同错误,所以我想我会分享我的愚蠢,以在未来几分钟内拯救一些可怜的疲惫的灵魂【参考方案3】:

我曾经得到过这个...这是因为我未能初始化指针,它指向随机垃圾。

【讨论】:

以上是关于C++:即使转换的对象不是 NULL,dynamic_cast 也会导致 SEGFAULT。怎么会这样?的主要内容,如果未能解决你的问题,请参考以下文章

java中json对象有没有方法可以把null值转换成空字符串

java中json对象有没有方法可以把null值转换成空字符串

我可以将 char* 缓冲区转换为对象类型吗?

将 NULL 指针转换为对象并调用其成员函数之一有实际好处吗?

为啥从 jquery 传递给控制器​​方法的参数即使不是 null 也是 null?

Flutter:类型 'Future<dynamic>' 不是类型 'Widget' 的子类型 // MaterialPageRoute<dynamic>(null))