C++ 为uu cxxabiv1::uu cxa_pure_virtual()-vtable ptr到抽象基类而崩溃?

C++ 为uu cxxabiv1::uu cxa_pure_virtual()-vtable ptr到抽象基类而崩溃?,c++,gcc,coredump,C++,Gcc,Coredump,我的应用程序崩溃: __cxxabiv1::__cxa_pure_virtual () 我能理解 根据下面的“1答案”,我可以练习一些测试程序: 1 #include <iostream> 2 3 class Base 4 { 5 public: 6 Base() 7 { 8 std::cout << "Base c'tor" << std::endl; 9 } 10 11

我的应用程序崩溃:

__cxxabiv1::__cxa_pure_virtual ()
我能理解

根据下面的“1答案”,我可以练习一些测试程序:

  1 #include <iostream>
  2 
  3 class Base
  4 {
  5 public:
  6     Base()
  7     {
  8         std::cout << "Base c'tor" << std::endl;
  9     }
 10 
 11     virtual ~Base()
 12     {
 13         std::cout << "Base d'tor" << std::endl;
 14     }
 15 
 16 };
 17 
 18 class Derived : public Base
 19 {
 20 public:
 21     Derived()
 22     : Base()
 23     {
 24         std::cout << "Derived c'tor" << std::endl;
 25     }
 26 
 27     ~Derived()
 28     {
 29         std::cout << "Derived d'tor" << std::endl;
 30     }
 31 };
 32 
 33 int
 34 main(
 35     int,
 36     char**)
 37 {
 38     {
 39         Derived d;
 40     }
 41     return 0;
 42 }
创建gdb批处理脚本:

break 8
command
p this
x/10xg this
x/10xg (long)*this
cont
end
break 13
command
p this
x/10xg this
x/10xg (long)*this
cont
end
break 24
command
p this
x/10xg this
x/10xg (long)*this
cont
end
break 29
command
p this
x/10xg this
x/10xg (long)*this
cont
end
run
并运行:

frank@frank-PC:~$ gdb ./test < gdb.bat |c++filt 

GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./test...done.
(gdb) Breakpoint 1 at 0x400b72: file test.cc, line 8.
(gdb) >>>>>(gdb) Breakpoint 2 at 0x400baa: file test.cc, line 13.
(gdb) >>>>>(gdb) Breakpoint 3 at 0x400c29: file test.cc, line 24.
(gdb) >>>>>(gdb) Breakpoint 4 at 0x400c81: file test.cc, line 29.
(gdb) >>>>>(gdb) Starting program: /home/frank/test 

Breakpoint 1, Base::Base (this=0x7fffffffdab0) at test.cc:8
8           std::cout << "Base c'tor" << std::endl;
$1 = (Base * const) 0x7fffffffdab0
0x7fffffffdab0: 0x0000000000400df8  0x597870ad9bc42900
0x7fffffffdac0: 0x0000000000400d10  0x00007ffff7495830
0x7fffffffdad0: 0x0000000000000000  0x00007fffffffdba8
0x7fffffffdae0: 0x00000001ffffdbb8  0x0000000000400ab6
0x7fffffffdaf0: 0x0000000000000000  0x9e98039144430dd4
0x400df8 <vtable for Base+16>:  0x0000000000400b92  0x0000000000400bde
0x400e08 <typeinfo for Derived>:    0x0000000000602200  0x0000000000400e20
0x400e18 <typeinfo for Derived+16>: 0x0000000000400e30  0x6465766972654437
0x400e28 <typeinfo name for Derived+8>: 0x0000000000000000  0x0000000000602090
0x400e38 <typeinfo for Base+8>: 0x0000000000400e40  0x0000006573614234
Base c'tor

Breakpoint 3, Derived::Derived (this=0x7fffffffdab0) at test.cc:24
24          std::cout << "Derived c'tor" << std::endl;
$2 = (Derived * const) 0x7fffffffdab0
0x7fffffffdab0: 0x0000000000400dd8  0x597870ad9bc42900
0x7fffffffdac0: 0x0000000000400d10  0x00007ffff7495830
0x7fffffffdad0: 0x0000000000000000  0x00007fffffffdba8
0x7fffffffdae0: 0x00000001ffffdbb8  0x0000000000400ab6
0x7fffffffdaf0: 0x0000000000000000  0x9e98039144430dd4
0x400dd8 <vtable for Derived+16>:   0x0000000000400c68  0x0000000000400ce2
0x400de8 <vtable for Base>: 0x0000000000000000  0x0000000000400e30
0x400df8 <vtable for Base+16>:  0x0000000000400b92  0x0000000000400bde
0x400e08 <typeinfo for Derived>:    0x0000000000602200  0x0000000000400e20
0x400e18 <typeinfo for Derived+16>: 0x0000000000400e30  0x6465766972654437
Derived c'tor

Breakpoint 4, Derived::~Derived (this=0x7fffffffdab0, __in_chrg=<optimized out>) at test.cc:29
29          std::cout << "Derived d'tor" << std::endl;
$3 = (Derived * const) 0x7fffffffdab0
0x7fffffffdab0: 0x0000000000400dd8  0x597870ad9bc42900
0x7fffffffdac0: 0x0000000000400d10  0x00007ffff7495830
0x7fffffffdad0: 0x0000000000000000  0x00007fffffffdba8
0x7fffffffdae0: 0x00000001ffffdbb8  0x0000000000400ab6
0x7fffffffdaf0: 0x0000000000000000  0x9e98039144430dd4
0x400dd8 <vtable for Derived+16>:   0x0000000000400c68  0x0000000000400ce2
0x400de8 <vtable for Base>: 0x0000000000000000  0x0000000000400e30
0x400df8 <vtable for Base+16>:  0x0000000000400b92  0x0000000000400bde
0x400e08 <typeinfo for Derived>:    0x0000000000602200  0x0000000000400e20
0x400e18 <typeinfo for Derived+16>: 0x0000000000400e30  0x6465766972654437
Derived d'tor

Breakpoint 2, Base::~Base (this=0x7fffffffdab0, __in_chrg=<optimized out>) at test.cc:13
13          std::cout << "Base d'tor" << std::endl;
$4 = (Base * const) 0x7fffffffdab0
0x7fffffffdab0: 0x0000000000400df8  0x597870ad9bc42900
0x7fffffffdac0: 0x0000000000400d10  0x00007ffff7495830
0x7fffffffdad0: 0x0000000000000000  0x00007fffffffdba8
0x7fffffffdae0: 0x00000001ffffdbb8  0x0000000000400ab6
0x7fffffffdaf0: 0x0000000000000000  0x9e98039144430dd4
0x400df8 <vtable for Base+16>:  0x0000000000400b92  0x0000000000400bde
0x400e08 <typeinfo for Derived>:    0x0000000000602200  0x0000000000400e20
0x400e18 <typeinfo for Derived+16>: 0x0000000000400e30  0x6465766972654437
0x400e28 <typeinfo name for Derived+8>: 0x0000000000000000  0x0000000000602090
0x400e38 <typeinfo for Base+8>: 0x0000000000400e40  0x0000006573614234
Base d'tor
[Inferior 1 (process 4962) exited normally]
(gdb) (gdb) quit
而我在调用堆栈上看到的最后一个d'tor是派生类。
那么这是一个指示器吗,内存对象已经被释放并再次用于其他对象实例

这怎么可能?这是由编译器完成的中间工作吗

对。通常,构造函数首先将vtable指针设置为自己类的vtable。然后,当派生类的构造函数运行时,它会用自己的指针覆盖vtable指针


这正好实现C++标准所要求的行为,在构造函数执行过程中调用虚函数(和析构函数;它们反转这些赋值)将对象视为构造函数的动态类型,而不是实际的完整对象。在纯虚函数的情况下,行为是未定义的;编译器通常会将此诊断存根插入vtable。

您是否有一个小的、可复制的测试用例显示问题?否则很难提供太多帮助。这只是一个存根,用于捕获永远不会发生的致命错误,非常有用。也许你试图调用一个切片指针?检查强制转换,等等它是否对析构函数执行相反的操作?不,实际上构造函数和析构函数都在开始时设置vtable(在典型的实现中)。区别在于调用基本版本的顺序。构造函数先调用基构造函数,然后运行自己的代码;析构函数先运行自己的代码,然后调用基析构函数。
frank@frank-PC:~$ gdb ./test < gdb.bat |c++filt 

GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./test...done.
(gdb) Breakpoint 1 at 0x400b72: file test.cc, line 8.
(gdb) >>>>>(gdb) Breakpoint 2 at 0x400baa: file test.cc, line 13.
(gdb) >>>>>(gdb) Breakpoint 3 at 0x400c29: file test.cc, line 24.
(gdb) >>>>>(gdb) Breakpoint 4 at 0x400c81: file test.cc, line 29.
(gdb) >>>>>(gdb) Starting program: /home/frank/test 

Breakpoint 1, Base::Base (this=0x7fffffffdab0) at test.cc:8
8           std::cout << "Base c'tor" << std::endl;
$1 = (Base * const) 0x7fffffffdab0
0x7fffffffdab0: 0x0000000000400df8  0x597870ad9bc42900
0x7fffffffdac0: 0x0000000000400d10  0x00007ffff7495830
0x7fffffffdad0: 0x0000000000000000  0x00007fffffffdba8
0x7fffffffdae0: 0x00000001ffffdbb8  0x0000000000400ab6
0x7fffffffdaf0: 0x0000000000000000  0x9e98039144430dd4
0x400df8 <vtable for Base+16>:  0x0000000000400b92  0x0000000000400bde
0x400e08 <typeinfo for Derived>:    0x0000000000602200  0x0000000000400e20
0x400e18 <typeinfo for Derived+16>: 0x0000000000400e30  0x6465766972654437
0x400e28 <typeinfo name for Derived+8>: 0x0000000000000000  0x0000000000602090
0x400e38 <typeinfo for Base+8>: 0x0000000000400e40  0x0000006573614234
Base c'tor

Breakpoint 3, Derived::Derived (this=0x7fffffffdab0) at test.cc:24
24          std::cout << "Derived c'tor" << std::endl;
$2 = (Derived * const) 0x7fffffffdab0
0x7fffffffdab0: 0x0000000000400dd8  0x597870ad9bc42900
0x7fffffffdac0: 0x0000000000400d10  0x00007ffff7495830
0x7fffffffdad0: 0x0000000000000000  0x00007fffffffdba8
0x7fffffffdae0: 0x00000001ffffdbb8  0x0000000000400ab6
0x7fffffffdaf0: 0x0000000000000000  0x9e98039144430dd4
0x400dd8 <vtable for Derived+16>:   0x0000000000400c68  0x0000000000400ce2
0x400de8 <vtable for Base>: 0x0000000000000000  0x0000000000400e30
0x400df8 <vtable for Base+16>:  0x0000000000400b92  0x0000000000400bde
0x400e08 <typeinfo for Derived>:    0x0000000000602200  0x0000000000400e20
0x400e18 <typeinfo for Derived+16>: 0x0000000000400e30  0x6465766972654437
Derived c'tor

Breakpoint 4, Derived::~Derived (this=0x7fffffffdab0, __in_chrg=<optimized out>) at test.cc:29
29          std::cout << "Derived d'tor" << std::endl;
$3 = (Derived * const) 0x7fffffffdab0
0x7fffffffdab0: 0x0000000000400dd8  0x597870ad9bc42900
0x7fffffffdac0: 0x0000000000400d10  0x00007ffff7495830
0x7fffffffdad0: 0x0000000000000000  0x00007fffffffdba8
0x7fffffffdae0: 0x00000001ffffdbb8  0x0000000000400ab6
0x7fffffffdaf0: 0x0000000000000000  0x9e98039144430dd4
0x400dd8 <vtable for Derived+16>:   0x0000000000400c68  0x0000000000400ce2
0x400de8 <vtable for Base>: 0x0000000000000000  0x0000000000400e30
0x400df8 <vtable for Base+16>:  0x0000000000400b92  0x0000000000400bde
0x400e08 <typeinfo for Derived>:    0x0000000000602200  0x0000000000400e20
0x400e18 <typeinfo for Derived+16>: 0x0000000000400e30  0x6465766972654437
Derived d'tor

Breakpoint 2, Base::~Base (this=0x7fffffffdab0, __in_chrg=<optimized out>) at test.cc:13
13          std::cout << "Base d'tor" << std::endl;
$4 = (Base * const) 0x7fffffffdab0
0x7fffffffdab0: 0x0000000000400df8  0x597870ad9bc42900
0x7fffffffdac0: 0x0000000000400d10  0x00007ffff7495830
0x7fffffffdad0: 0x0000000000000000  0x00007fffffffdba8
0x7fffffffdae0: 0x00000001ffffdbb8  0x0000000000400ab6
0x7fffffffdaf0: 0x0000000000000000  0x9e98039144430dd4
0x400df8 <vtable for Base+16>:  0x0000000000400b92  0x0000000000400bde
0x400e08 <typeinfo for Derived>:    0x0000000000602200  0x0000000000400e20
0x400e18 <typeinfo for Derived+16>: 0x0000000000400e30  0x6465766972654437
0x400e28 <typeinfo name for Derived+8>: 0x0000000000000000  0x0000000000602090
0x400e38 <typeinfo for Base+8>: 0x0000000000400e40  0x0000006573614234
Base d'tor
[Inferior 1 (process 4962) exited normally]
(gdb) (gdb) quit
__cxxabiv1::__cxa_pure_virtual ()