派生类 vtable 已损坏?

发布于 2024-10-08 17:37:18 字数 847 浏览 5 评论 0原文

需要帮助解决导致 vtable 损坏问题的根本问题(不确定是否发生了这种情况)。这是代码的非常简化的版本。

class CBase
{
public:
    CBase()
    virtual ~CBase()
    virtual void base_virtual_fn1() = 0;
    virtual void base_virtual_fn2();
private:
    CData   _data;
};

class CDerived : public CBase
{
public:
    CDerived();
    virtual ~CDerived()
    virtual void base_virtual_fn1();
    virtual void base_virtual_fn2();
    virtual void derived_virtual_fn1();
    virtual void derived_virtual_fn2();
private:
    // Contains vectors , maps, integers, bools. 
};

当我创建 CDerived 的实例并调用派生类虚拟函数(例如导出的_virtual_fn2)时,另一个函数将被调用,即导出的_virtual_fn1。

对 base_virtual_fnx 的调用没有问题。

这只发生在堆上创建的对象上,而不是本地对象上。

这些类位于共享库中。我在 Linux (SLES 10) 上使用 gcc 3.4.2。此代码中没有 pragma pack 指令,并且混合了 C 和 C++ 代码(使用 extern c)。 这里可能有什么问题?

我忘了提及还有大量其他代码(可执行文件、库)

Need help in root causing a vtable corruption issue(not sure if that’s what is happening). Here is the very simplified version of the code.

class CBase
{
public:
    CBase()
    virtual ~CBase()
    virtual void base_virtual_fn1() = 0;
    virtual void base_virtual_fn2();
private:
    CData   _data;
};

class CDerived : public CBase
{
public:
    CDerived();
    virtual ~CDerived()
    virtual void base_virtual_fn1();
    virtual void base_virtual_fn2();
    virtual void derived_virtual_fn1();
    virtual void derived_virtual_fn2();
private:
    // Contains vectors , maps, integers, bools. 
};

When I create an instance of CDerived and call the derived class virtual function say derived_virtual_fn2 the other function gets called i.e. derived_virtual_fn1.

Calls to base_virtual_fnx has no issues.

This only happens with object created on the heap and not for local object.

These classes are in a shared library. I’m using gcc 3.4.2 on Linux (SLES 10). There is no pragma pack directive in any of this code and there is a mix of C and C++ code (extern c is used).
What could be the issue here?

I forgot to mention that there are there is tons of other code (executable, libraries)

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

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

发布评论

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

评论(5

皇甫轩 2024-10-15 17:37:18

这是我犯的一个严重错误,我花了很长时间才发现。编译器/调试器/valgrind 没有让我了解发生了什么。应该有办法调试这些类型的错误:

基类是在定义了“SOME_PACKAGE”的库中编译的:

class interface {
    virtual int function1(int);
#ifdef SOME_PACKAGE
    virtual int function2(int);
#endif
    virtual int function3(int);
}

class base : public interface {
    int function1(int);
    int function2(int);
    int function3(int);
}

派生类是稍后编译的,没有 SOME_PACKAGE 定义的

class derived : public base {
    int function1(int);
    int function3(int);
}

对 function3 的调用导致跳转到 function2,我最终能够弄清楚调试器,但我花了很长时间才找到原因。

Here is a nasty mistake I made that took me forever to find. The compiler/debugger/valgrind gave me no insight into what was going on. There should be someway to debug these kinds of errors:

The base class was compiled in a library with "SOME_PACKAGE" defined:

class interface {
    virtual int function1(int);
#ifdef SOME_PACKAGE
    virtual int function2(int);
#endif
    virtual int function3(int);
}

class base : public interface {
    int function1(int);
    int function2(int);
    int function3(int);
}

The derived class was compiled later without SOME_PACKAGE defined

class derived : public base {
    int function1(int);
    int function3(int);
}

calls to function3 caused jumps to function2 which I was eventually able to figure out with the debugger, but it took me a long time to find the cause.

在风中等你 2024-10-15 17:37:18

如果它只发生在堆上创建的对象上,最可能的解释是堆损坏,这可能与您提到的两个类无关。检查您的分配/解除分配!检查您是否正确使用delete []来删除数组等。也许也可以使用valgrind或类似的。

If it only happens for objects created on the heap, the most likely explanation is heap corruption, which possibly has nothing to do with the two classes you mention. Check your allocations/deallocations! check that you're correctly using delete [] to delete arrays, etc. Maybe use valgrind or similar as well.

陈独秀 2024-10-15 17:37:18

抱歉,我对这个线程进行了死灵攻击,但是在调试类似的问题时,我终于找到了一个可能的答案,但这里尚未列出,我相信这对于其他遇到此类问题的人来说是有益的。

答案(就我而言)是,仍然安装了部分代码,但是我们的构建系统无法确保测试实际上会链接到新且正确编译的版本。相反,加载的动态库需要与调用它们的代码不同的 vtable 布局。

当然,可能的症状是执行了错误的函数,或者对虚拟函数的调用因分段错误而失败。这实际上取决于两个版本之间 vtable 布局如何变化。

如果这是问题背后的原因,make uninstall 应该可以修复它。

Sorry for necromancing this thread, but when debugging a similar problem, I finally found a possible answer that is not yet listed here, and I believe it will be beneficial for other people stumbling across this kind of problem.

The answer (in my case) is, that there were still parts of the code installed, our build system, however, was not able to ensure that the tests would actually link against the freshly and correctly compiled versions. Instead, dynamic libraries were loaded which expected a different vtable layout than the code that called them.

Of course, possible symptoms are that wrong functions get executed, or that the very call to a virtual function fails with a segmentation fault. It really depends on how the vtable layout changed between the two versions.

If this is the reason behind your problem, make uninstall should fix it.

安人多梦 2024-10-15 17:37:18

你向我们展示的几乎没有什么令人震惊的;-)

当我碰巧对内存损坏一无所知时,我习惯于打开该实用程序gflags 开启。这是相当明智的一个小应用程序,可以在许多犯罪行为引发不合逻辑的噩梦之前检测到它们。然而,这使得事情变得非常缓慢。

尝试理解 gflags 尖叫的大部分步骤。

There's nothing shocking in the almost nothing you show us ;-)

When I happen to understand nothing about the memory corruption, I'm used to turning the utility gflags on. It is pretty sensible a little application and detect many criminal things, far before they provoke unlogical nightmares. However it makes things turns really slow.

Try understanding most of the steps where gflags screams.

杀お生予夺 2024-10-15 17:37:18

这几乎总是陈旧的对象。清理或尝试在链接器路径中查找过时的目标文件。

This is almost always stale objects. Make clean or attempt to locate stale object files in your linker path.

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