C++ “警告:无法找到值 XXX 值的虚拟表的链接器符号”使用 GCC 和 GDB(代码块)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8695411/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Warning: Can't find linker symbol for virtual table for value XXX value" using GCC and GDB (CodeBlocks)
提问by Heathcliff
I'm getting a runtime error ("memory can't be written") that, after inspection through the debugger, leads to the warning in the tittle.
我收到一个运行时错误(“内存无法写入”),在通过调试器检查后,会导致标题中出现警告。
The headers are the following:
标题如下:
componente.h:
组件.h:
#ifndef COMPONENTE_H
#define COMPONENTE_H
using namespace std;
class componente
{
int num_piezas;
int codigo;
char* proovedor;
public:
componente();
componente(int a, int b, const char* c);
virtual ~componente();
virtual void print();
};
#endif // COMPONENTE_H
complement.h implementation
补充.h实现
#include "Componente.h"
#include <string.h>
#include <iostream>
componente::componente()
{
num_piezas = 0;
codigo = 0;
strcpy(proovedor, "");
//ctor
}
componente::componente(int a = 0, int b = 0, const char* c = "")
{
num_piezas = a;
codigo = b;
strcpy(proovedor, "");
}
componente::~componente()
{
delete proovedor;//dtor
}
void componente::print()
{
cout << "Proovedor: " << proovedor << endl;
cout << "Piezas: " << num_piezas << endl;
cout << "Codigo: " << codigo << endl;
}
teclado.h
teclado.h
#ifndef TECLADO_H
#define TECLADO_H
#include "Componente.h"
class teclado : public componente
{
int teclas;
public:
teclado();
teclado(int a, int b, int c, char* d);
virtual ~teclado();
void print();
};
#endif // TECLADO_H
teclado.h implementation
teclado.h 实现
#include "teclado.h"
#include <iostream>
teclado::teclado() : componente()
{
teclas = 0;//ctor
}
teclado::~teclado()
{
teclas = 0;//dtor
}
teclado::teclado(int a = 0, int b = 0, int c = 0, char* d = "") : componente(a,b,d)
{
teclas = c;
}
void teclado::print()
{
cout << "Teclas: " << teclas << endl;
}
The main method where I get the runtime error is the following:
我得到运行时错误的主要方法如下:
#include <iostream>
#include "teclado.h"
using namespace std;
int main()
{
componente a; // here I have the breakpoint where I check this warning
a.print();
return 0;
}
BUT, if instead of creating an "componente" object, I create a "teclado" object, I don't get the runtime error. I STILL get the warning during debugging, but the program behaves as expected:
但是,如果不是创建“componente”对象,而是创建“teclado”对象,则不会出现运行时错误。在调试期间我仍然收到警告,但程序按预期运行:
#include <iostream>
#include "teclado.h"
using namespace std;
int main()
{
teclado a;
a.print();
return 0;
}
This returns "Teclas = 0" plus the "Press any key..." thing.
这将返回“Teclas = 0”加上“按任意键...”的东西。
Do you have any idea why the linker is having troube with this? It doesn't show up when I invoke the virtual function, but before, during construction.
你知道为什么链接器会遇到这个问题吗?当我调用虚函数时它不会出现,但是在构造之前。
回答by hmjd
Two errors that I can see:
我可以看到的两个错误:
strcpy(proovedor, ""); // No memory has been allocated to `proovedor` and
// it is uninitialised.
As it is uninitialised this could be overwriting anywhere in the process memory, so could be corrupting the virtual table.
由于未初始化,这可能会覆盖进程内存中的任何位置,因此可能会损坏虚拟表。
You could change this to (in both constructors):
您可以将其更改为(在两个构造函数中):
proovedor = strdup("");
Destructor uses incorrect delete
on proovedor
:
析构函数使用不正确delete
的proovedor
:
delete proovedor; // should be delete[] proovedor
As this is C++ you should considering using std::string
instead of char*
.
由于这是 C++,您应该考虑使用std::string
而不是char*
.
If you do not change to std::string
then you need to either:
如果您不更改为,std::string
则您需要:
- Implement a copy constructor and assignment operator as the default versions are incorrect if you have a member variable that is dynamically allocated, or
- Make the copy constructor and assignment operator private to make it impossible for them to be used.
- 如果您有动态分配的成员变量,则实现复制构造函数和赋值运算符,因为默认版本不正确,或者
- 将复制构造函数和赋值运算符设为私有,使其无法使用。
回答by sage
Another source of this same message is that gdb can get confused by not-yet-initialized variables. (This answers the question title, but not the OP's question, since a web search led me here looking for an answer.)
同样消息的另一个来源是 gdb 可能会被尚未初始化的变量混淆。(这回答了问题标题,但不是 OP 的问题,因为网络搜索使我在这里寻找答案。)
Naturally, you shouldn't have uninitialized variables, but in my case gdb attempts to show function local variables even before they are declared/initialized.
自然,您不应该有未初始化的变量,但在我的情况下,gdb 甚至在声明/初始化之前尝试显示函数局部变量。
Today I'm stepping through another developer's gtest case and this message was getting dumped to output every time the debugger stopped. In this case, the variable in question was declared on ~line 245, but the function started on ~line 202. Every time I stopped the debugger between these lines, I received the message.
今天我正在逐步完成另一个开发人员的 gtest 案例,每次调试器停止时,这条消息都会被转储到输出。在这种情况下,有问题的变量在 ~line 245 上声明,但函数在 ~line 202 上启动。每次我在这些行之间停止调试器时,我都会收到消息。
I worked around the issue by moving the variable declaration to the top of the function.
我通过将变量声明移到函数顶部来解决这个问题。
For reference, I am testing with gdb version 7.11.1 in QtCreator 4.1.0 and I compiled with g++ version 5.4.1
作为参考,我在 QtCreator 4.1.0 中使用 gdb 7.11.1 版进行测试,并使用 g++ 5.4.1 版进行编译