【发布时间】:2011-11-01 11:53:40
【问题描述】:
我有下面的类结构(细节省略)。
Environment.h
#include "SimEnv.h"
class Environment : public SimEnv {
public:
virtual int functionA(int arg) {
printf("I'm in functionA\n");
. . .
}
virtual int functionB(int arg) {
printf("I'm in functionB\n");
. . .
}
};
DerivedEnv.h
#include "Environment.h"
class DerivedEnv : public Environment {
public:
DerivedEnv(GrandParentClass* grandpaClass) : Environment() { . . . }
};
ParentClass.h
#include "GrandParentClass.h"
#include "Environment.h"
class ParentClass : public GrandParentClass {
public:
ParentClass() {
printf("In ParentClass constructor\n");
m_pEnv = new DerivedEnv(this);
m_pEnv->functionB(val);
}
protected:
Environment* m_pEnv;
virtual void thisFunct() {
printf("Calling functionB from ParentClass::thisFunct()\n");
m_pEnv->functionB(val);
}
};
DerivedClass.h
#include "ParentClass.h"
class DerivedClass : public ParentClass {
public:
DerivedClass() : ParentClass() {
printf("In DerivedClass constructor\n");
m_pEnv->functionB(val);
}
void thatFunct {
printf("Calling functionB from DerivedClass::thatFunct()\n");
m_pEnv->functionB(val);
}
void sim() {
thisFunct();
printf("Calling functionB from DerivedClass::sim()\n");
m_pEnv->functionB(val);
}
};
main.cc
#include "DerivedClass.h"
void main() {
. . .
static DerivedClass derivedClass;
derivedClass.sim();
. . .
}
我遇到的问题是,当我运行我的代码并实例化 DerivedClass 时,我得到以下信息:
In ParentClass constructor
I'm in functionB
In DerivedClass constructor
I'm in functionA
Calling functionB from ParentClass::thisFunct()
I'm in functionB
Calling functionB from DerivedClass::sim()
I'm in functionA
所以我的程序在 ParentClass 的构造函数中调用了正确的虚函数,但随后在 DerivedClass 的构造函数中调用了错误的函数。这是我到目前为止检查过的内容:
- 我已经确定这不是我的构建被破坏的问题。
- 我已经在ParentClass 的构造函数和DerivedClass 的构造函数中使用
p /a (*(void ***)m_pEnv)[0]@30打印出gdb 中的vtable。两个 vtable 显示相同
我在互联网上搜索过,似乎这些类型的问题可能是由于堆栈损坏造成的。真的吗?我该如何调试它?这个问题还有其他解释吗?
加法 我进一步调试并意识到这里似乎存在上下文问题。当我从任何 ParentClass 的成员函数调用 functionB 时,它确实正确执行它。
似乎只是从 DerivedClass 调用到了错误的函数。
我已修改伪代码以突出显示这一点。
【问题讨论】:
-
能否请您不要省略重要的细节,例如
m_pEnv?实际上,废弃它——请发布真实的、可编译的代码,而不是伪代码。不然麻烦太多了。制作一个最小的、完整的示例来展示您的问题。 -
修复了这个伪代码的所有问题后,我的版本在两行都打印了
I'm in functionB。我的投票是“它在其他地方坏了”。 -
伪代码没有显示任何类曾经引用functionA,请在真实代码中用functionA解释完整模式。
-
感谢您的 cmets。不幸的是,发布真正的代码是不切实际的。它实际上是跨越数百个文件的多线程 Verilog/C++/SystemC 协同仿真环境的一部分。所以很可能是“它在其他地方坏了”。我知道在没有所有信息的情况下很难给出建议,我并不期待完整的解决方案,我会很高兴有关于如何进行调试的建议或想法。
-
我唯一一次看到编译器从一个函数转到另一个函数(不是不同的虚拟重载)是在头文件中添加虚拟函数后没有重新编译某些东西。我会首先仔细检查构建,即使这意味着删除所有库/对象并从头开始构建。
标签: c++ constructor gdb virtual-functions