对 vtable 的未定义引用 - 虚拟成员,由 gsoap 生成的类

发布于 2024-10-09 23:15:12 字数 1006 浏览 3 评论 0原文

gsoap 及其工具 wsdl2h 和soapcpp2 为我提供了一个soapStub.h 文件,其中包含以下内容:

class SOAP_CMAC ns2__SOAPKunden
{
  public:
    std::string *adresszusatz; 
    // ...
  public:
    virtual int soap_type() const { return 7; }
    // ...
    ns2__SOAPKunden() : adresszusatz(NULL), x(NULL) { }   // left out all member init.
    virtual ~ns2__SOAPKunden() { }
};

我从一个小应用程序开始,使用该类用来自informix DB 的数据填充对象。

但是为了成功编译,我必须放弃所有虚拟的东西 - 我发现很多关于这个错误和在子类中使用虚拟成员的帖子 - 否则我承认

main.o: In function `ns2__SOAPKunden::ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenC1Ev[ns2__SOAPKunden::ns2__SOAPKunden()]+0xf): undefined reference to `vtable for ns2__SOAPKunden'
main.o: In function `ns2__SOAPKunden::~ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenD1Ev[ns2__SOAPKunden::~ns2__SOAPKunden()]+0x13): undefined reference to `vtable for ns2__SOAPKunden'
collect2: ld returned 1 exit status

经过多年的脚本编写,我很难理解 C++ 代码...我想寻求任何建议,下一步该尝试什么。我的类不是派生类,这让我感到好奇。

gsoap with its tools wsdl2h and soapcpp2 provided me with a soapStub.h file containing the following:

class SOAP_CMAC ns2__SOAPKunden
{
  public:
    std::string *adresszusatz; 
    // ...
  public:
    virtual int soap_type() const { return 7; }
    // ...
    ns2__SOAPKunden() : adresszusatz(NULL), x(NULL) { }   // left out all member init.
    virtual ~ns2__SOAPKunden() { }
};

I start with a small app using the class to populate objects with data from informix DB.

But to compile successfully i have to leave away all the virtual stuff - i found many postings about this error and use of virtual members in subclasses - otherwise i get

main.o: In function `ns2__SOAPKunden::ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenC1Ev[ns2__SOAPKunden::ns2__SOAPKunden()]+0xf): undefined reference to `vtable for ns2__SOAPKunden'
main.o: In function `ns2__SOAPKunden::~ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenD1Ev[ns2__SOAPKunden::~ns2__SOAPKunden()]+0x13): undefined reference to `vtable for ns2__SOAPKunden'
collect2: ld returned 1 exit status

I admit after years of scripting only it's very hard for me to make sense of C++ code... I want to ask for any advice what to try next. My class is no derived class, is for example what makes me wonder.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

划一舟意中人 2024-10-16 23:15:12

该错误意味着虚拟表尚未在最终二进制文件(可执行文件或库)中正确编译/链接。有两种常见情况会导致此错误:

  • 您没有链接包含虚拟表定义的目标文件 - 即您将 soapStub.cpp 编译为 soapStub.o ,但没有将该二进制文件添加到链接器命令行中。
  • 编译器不会在任何地方生成虚拟表,因此即使您包含所有目标文件,也不包含虚拟表。

对于没有经验的开发人员来说,第二种情况最难识别,可能是由标头中定义的包含虚函数的类引起的。如果所有的虚函数都是内联定义的,编译器会在包含头的所有翻译单元中生成虚表,并将其标记为弱符号,以便链接器可以丢弃它们,但如果稍后添加新的虚方法并且如果您在标头中保留其未定义,或者如果从其中一个虚拟函数中删除定义,那么编译器将不会在每个翻译单元中生成虚拟表,而只会在定义这些函数的翻译单元中生成虚拟表。

要检查的事情:

  • 您正在链接所有目标文件
  • ,或者所有虚拟函数都在类定义中内联定义,或者您有一个定义虚拟函数的 .cpp 并且您正在链接它。

The error means that the virtual table has not been correctly compiled/linked in the final binary (executable or library). There are two common circumstances that lead to this error:

  • you are not linking the object file that includes the virtual table definitions --i.e. you compiled soapStub.cpp into soapStub.o, but did not add that binary to the linker command line.
  • the compiler is not generating the virtual table anywhere, so even if you are including all object files, that does not include the virtual table.

The second case is the hardest to identify for non-experienced developers, and can be caused by a class that is defined in the header and contains virtual functions. If all the virtual functions are defined inlined, the compiler will generate the virtual table in all translation units that include the header, and mark it as a weak symbol so that the linker can discard them, but if you later add a new virtual method and you leave it undefined in the header --or if you remove the definition from one of the virtual functions--, then the compiler will not generate the virtual table in each translation unit, but only in the one that defines those functions.

Things to check:

  • you are linking all object files
  • either all virtual functions are defined inline in the class definition or you have a .cpp that defines the virtual functions and you are linking that in.
找回味觉 2024-10-16 23:15:12

这就是大卫·罗德里格斯所说的,我想只是说得更简单......

我在我的接口类中遇到了这种情况:

class IBase
{
    public:
    virtual void begin(unsigned long);
    virtual void end();
    virtual int available(void) = 0;
    virtual int peek(void) = 0;
    virtual int read(void) = 0;
    virtual void flush(void) = 0;
}

并将其更改为:

class IBase
{
    public:
    virtual void begin(unsigned long) = 0;
    virtual void end() = 0;
    virtual int available(void) = 0;
    virtual int peek(void) = 0;
    virtual int read(void) = 0;
    virtual void flush(void) = 0;
}

这起到了作用。

begin() 和 end() 在不同文件的派生类中定义,IBase 类(接口)仅在标头中声明并包含在少数地方。

仅当我将优化设置为无(-O0)时,OP 错误才会出现,任何其他设置都不会导致错误(gcc 4.8)。

This is what David Rodriguez said, just stated simpler I guess...

I had this situation in my interface class:

class IBase
{
    public:
    virtual void begin(unsigned long);
    virtual void end();
    virtual int available(void) = 0;
    virtual int peek(void) = 0;
    virtual int read(void) = 0;
    virtual void flush(void) = 0;
}

and changed it to this:

class IBase
{
    public:
    virtual void begin(unsigned long) = 0;
    virtual void end() = 0;
    virtual int available(void) = 0;
    virtual int peek(void) = 0;
    virtual int read(void) = 0;
    virtual void flush(void) = 0;
}

which did the trick.

begin() and end() were defined in derived class in a different file, IBase class (interface) was only declared in header and included in few places.

Error from OP only appeared when I set optimizations to none (-O0), any other setting resulted in no error (gcc 4.8).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文