gpt4 book ai didi

c++ - 关于这个在 Linux 上用 gcc 编译的程序中的 vtable,nm 告诉我什么?

转载 作者:太空狗 更新时间:2023-10-29 23:43:37 26 4
gpt4 key购买 nike

我将一个基类更改为抽象类(即我将其中一个方法设为纯虚拟)并重新编译它。当我将它与派生类链接时,链接器提示 vtable。我用 nm 调查了一些事情,但我不确定 nm 到底告诉了我什么。我只是通过删除 *.o 文件并重新编译 Derived 类来修复问题,但我想了解这里的 vtable 到底发生了什么。

我原来的代码是这样的:

基础.h

class Base {
public:
virtual void doSomething();
};

基础.cpp

#include <iostream>
#include <Base.h>
void Base::doSomething() {
std::cout << "Base::doSomething()" << "\n";
}

派生.h

#include <Base.h>
class Derived : public Base {
public:
Derived();
void doSomething() override;
};

派生.cpp

#include <iostream>
#include <Derived.h>
Derived::Derived() {
std::cout << "Derived::Derived() constructor" << "\n";
}
void Derived::doSomething() {
std::cout << "Derived::doSomething()" << "\n";
}

Makefile 包含以下内容:

CXXFLAGS = -std=c++14 -pedantic -Wall -Werror -I ./

default: build
clean:
rm -f proggy
rm -f *.o

proggy: proggy.o Base.o Derived.o
g++ -o proggy proggy.o Base.o Derived.o

Base.o: Base.cpp Base.h
Derived.o: Derived.cpp Derived.h

然后我运行 make,一切正常。作为记录,我此时也运行了 nm,如下所示:

$ nm -C Derived.o | grep Base
00000000 W Base::Base()
00000000 W Base::Base()
00000000 n Base::Base()
U typeinfo for Base
U vtable for Base

我看到 Base 的类型信息 是未定义的,但似乎对此很满意。

此外,在 Base.o 中,现阶段是这样的:

nm -C Base.o | grep Base
000000d4 t _GLOBAL__sub_I__ZN4Base11doSomethingEv
00000000 T Base::doSomething()
00000044 R typeinfo for Base
0000004c R typeinfo name for Base
00000038 R vtable for Base

然后我按如下方式修改 Base.h 和 Base.cpp 以使类抽象:

基础.h

class Base {
public:
virtual void doSomething() = 0; // pure virtual
};

基础.cpp

#include <iostream>
#include <Base.h>
// void Base::doSomething() {
// std::cout << "Base::doSomething()" << "\n";
// }

然后当我运行 make 时,我得到了这个错误:

$ make proggy
g++ -std=c++14 -pedantic -Wall -Werror -I ./ -c -o Base.o Base.cpp
g++ -o proggy proggy.o Base.o Derived.o
Derived.o:(.rodata+0x5c): undefined reference to `typeinfo for Base'
Derived.o: In function `Base::Base()':
Derived.cpp:(.text._ZN4BaseC2Ev[_ZN4BaseC5Ev]+0x48): undefined reference to `vtable for Base'
collect2: error: ld returned 1 exit status
Makefile:17: recipe for target 'proggy' failed
make: *** [proggy] Error 1

其中 c++filt 告诉我以下内容:

$ c++filt _ZN4BaseC2Ev
Base::Base()

然后我按如下方式运行 nm,它告诉我:

$ nm -C Derived.o | grep Base
00000000 W Base::Base()
00000000 W Base::Base()
00000000 n Base::Base()
U typeinfo for Base
U vtable for Base

我可以看到 Base 的类型信息 是未定义的,但它也是在最开始的时候,所以我认为这不是一个问题,但它是。另请注意,现在 Base.o 中没有提及 Base。

$ nm -C Base.o | grep Base  

即此 nm 和 grep 命令未找到任何内容。

最后,我删除了所有 *.o 文件并再次运行 make,一切都恢复正常。然后我运行 nm 以查看 nm 报告的内容,它报告了以下内容:

$ nm -C Derived.o | grep Base
00000000 W Base::Base()
00000000 W Base::Base()
00000000 n Base::Base()
00000000 V typeinfo for Base
00000000 V typeinfo name for Base
00000000 V vtable for Base

这是什么意思?

我的问题是:

  1. nm 在这里告诉我什么以及之前的错误是什么虚表?
  2. 衍生需要哪些它没有的?
  3. 为什么重新编译派生类可以解决问题,这是做什么的修复有关 vtable 的问题?

最佳答案

来自日志

$ make proggy
g++ -std=c++14 -pedantic -Wall -Werror -I ./ -c -o Base.o Base.cpp
g++ -o proggy proggy.o Base.o Derived.o

这意味着您的 makefile 不会重新构建 Derived.o,而只会重新构建 Base.o。这当然会导致问题。

您需要修复 Makefile 以将 Derive.cpp 的适当依赖项添加到 Base.h

关于c++ - 关于这个在 Linux 上用 gcc 编译的程序中的 vtable,nm 告诉我什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45835243/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com