具有 C++ 虚函数时的 GDB 不完整类型
GDB incomplete type when having C++ virtual function
我刚刚注意到一些奇怪的事情,当我在我的 class 中添加 "virtual keyword"(除构造函数之外的任何函数)时,我无法在 GDB 中显示我的对象的内容。 GDB 说 "incomplete type"
这是代码:
////////////////reco.h /////////////
#ifndef RECO_H
#define RECO_H
#include <iostream>
#include <string>
class reco {
public:
reco(float weight);
~reco(void);
float getWeight();
private:
float weight;
};
#endif
/////////////////reco.cpp ////////////
#include <iostream>
#include <string>
#include "reco.h"
using namespace std;
reco::reco(float weight) {
weight = weight;
}
reco::~reco(void) {
cout << "destructor reco" << endl;
}
float reco::getWeight() {
return weight;
}
////////////// main.cpp /////////////
#include <iostream>
#include <string>
#include "reco.h"
using namespace std;
int main() {
reco* s = new reco(5.0);
cout << s->getWeight() << endl;
delete s;
return 0;
}
然后用 GDB :
gdb main.exe
breakpoint main.cpp:11 <---- (cout)
run
print *s
= { weight = 5 }
然后,如果我创建其中一个函数 "virtual",然后我再次尝试使用 GDB 打印我的 *s
指针,它说:
"incomplete type"
VTABLE 似乎发生了一些事情,好像 "virtual" 关键字隐藏了我的 Reco class 的实现。我知道编译器会进行后期绑定,然后 VTABLE 查找是在运行时完成的,但是程序已经 运行 而 GDB 正在调试它,对吗?
"set print vtbl"设置在"on".
如果我使用 ptype s
,我会再次收到 <incomplete type>
消息。
如果我用 x/540f80
检查地址,它说 "cannot access memory"
我不知道为什么只添加这个关键字会使我的对象的类型不完整?
非常感谢您的帮助!
我注意到的最后一件事:
虚拟:
reco.cpp -> g0 and main.cpp -> g = incomplete type
reco.cpp -> g and main.cpp ->g = ok
没有虚拟
reco.cpp -> g0 and main.cpp -> g = ok
reco.cpp -> g and main.cpp ->g = ok
reco.cpp -> g and main.cpp ->g = ok
假设 -> g
你的意思是你用 -g
标志编译 reco.cpp
,是的 do,并且 不要这样做:
g++ -c -g0 reco.cpp
您发现 GCC 可以优化它必须发出的调试信息的数量 如果 它知道您有一个 key method.
没有virtual
,就没有关键方法,GCC 必须将冗余 调试信息发送到每个 编译单元。这会使您的目标文件更大(它应该对最终的可执行文件影响很小或没有影响),但允许您进行调试,即使只有部分目标文件是使用调试信息编译的。
我刚刚注意到一些奇怪的事情,当我在我的 class 中添加 "virtual keyword"(除构造函数之外的任何函数)时,我无法在 GDB 中显示我的对象的内容。 GDB 说 "incomplete type"
这是代码:
////////////////reco.h /////////////
#ifndef RECO_H
#define RECO_H
#include <iostream>
#include <string>
class reco {
public:
reco(float weight);
~reco(void);
float getWeight();
private:
float weight;
};
#endif
/////////////////reco.cpp ////////////
#include <iostream>
#include <string>
#include "reco.h"
using namespace std;
reco::reco(float weight) {
weight = weight;
}
reco::~reco(void) {
cout << "destructor reco" << endl;
}
float reco::getWeight() {
return weight;
}
////////////// main.cpp /////////////
#include <iostream>
#include <string>
#include "reco.h"
using namespace std;
int main() {
reco* s = new reco(5.0);
cout << s->getWeight() << endl;
delete s;
return 0;
}
然后用 GDB :
gdb main.exe
breakpoint main.cpp:11 <---- (cout)
run
print *s
= { weight = 5 }
然后,如果我创建其中一个函数 "virtual",然后我再次尝试使用 GDB 打印我的 *s
指针,它说:
"incomplete type"
VTABLE 似乎发生了一些事情,好像 "virtual" 关键字隐藏了我的 Reco class 的实现。我知道编译器会进行后期绑定,然后 VTABLE 查找是在运行时完成的,但是程序已经 运行 而 GDB 正在调试它,对吗?
"set print vtbl"设置在"on".
如果我使用 ptype s
,我会再次收到 <incomplete type>
消息。
如果我用 x/540f80
检查地址,它说 "cannot access memory"
我不知道为什么只添加这个关键字会使我的对象的类型不完整?
非常感谢您的帮助!
我注意到的最后一件事:
虚拟:
reco.cpp -> g0 and main.cpp -> g = incomplete type
reco.cpp -> g and main.cpp ->g = ok
没有虚拟
reco.cpp -> g0 and main.cpp -> g = ok
reco.cpp -> g and main.cpp ->g = ok
reco.cpp -> g and main.cpp ->g = ok
假设 -> g
你的意思是你用 -g
标志编译 reco.cpp
,是的 do,并且 不要这样做:
g++ -c -g0 reco.cpp
您发现 GCC 可以优化它必须发出的调试信息的数量 如果 它知道您有一个 key method.
没有virtual
,就没有关键方法,GCC 必须将冗余 调试信息发送到每个 编译单元。这会使您的目标文件更大(它应该对最终的可执行文件影响很小或没有影响),但允许您进行调试,即使只有部分目标文件是使用调试信息编译的。