“警告:找不到值 XXX 值的虚拟表的链接器符号”使用 GCC 和 GDB(代码块)

发布于 2024-12-23 16:48:35 字数 2384 浏览 5 评论 0原文

我收到一个运行时错误(“内存无法写入”),在通过调试器检查后,导致标题中出现警告。

标头如下:

componente.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 实现

#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

#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 实现

#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;
}

我得到运行时错误的主要方法如下:

#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;
}

但是,如果我创建一个“而不是创建一个“componente”对象,而不是创建一个“ teclado”对象,我没有收到运行时错误。我在调试过程中仍然收到警告,但程序的行为符合预期:

#include <iostream>
#include "teclado.h"

using namespace std;

int main()
{
    teclado a;
    a.print();
    return 0;
}

这将返回“Teclas = 0”加上“按任意键...”的内容。

您知道为什么链接器会遇到这个问题吗?当我调用虚函数时,它不会出现,而是在构造期间之前出现。

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:

#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

#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

#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

#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:

#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.

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.

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

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

发布评论

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

评论(2

白昼 2024-12-30 16:48:35

我可以看到两个错误:

strcpy(proovedor, "");  // No memory has been allocated to `proovedor` and
                        // it is uninitialised.

由于它未初始化,这可能会覆盖进程内存中的任何位置,因此可能会损坏虚拟表。

您可以将其更改为(在两个构造函数中):

proovedor = strdup("");

析构函数在 proovedor 上使用不正确的 delete

delete proovedor; // should be delete[] proovedor

由于这是 C++,您应该考虑使用 std::string > 而不是 char*

如果您不更改为 std::string 那么您需要:

  1. 实现复制构造函数和赋值运算符,因为如果您有动态分配的成员变量,则默认版本不正确,或者
  2. 将复制构造函数和赋值运算符设为私有,以使其无法使用。

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; // should be delete[] proovedor

As this is C++ you should considering using std::string instead of char*.

If you do not change to std::string then you need to either:

  1. Implement a copy constructor and assignment operator as the default versions are incorrect if you have a member variable that is dynamically allocated, or
  2. Make the copy constructor and assignment operator private to make it impossible for them to be used.
溺ぐ爱和你が 2024-12-30 16:48:35

同一消息的另一个来源是 gdb 可能会因尚未初始化的变量而感到困惑。 (这回答了问题标题,但不是OP的问题,因为网络搜索引导我在这里寻找答案。)

当然,你不应该有未初始化的变量,但在我的例子中,gdb甚至在它们之前就尝试显示函数局部变量被声明/初始化。

今天,我正在单步执行另一位开发人员的 gtest 案例,每次调试器停止时,此消息都会转储到输出。在本例中,相关变量是在第 245 行声明的,但该函数是在第 202 行启动的。每次我在这些行之间停止调试器时,都会收到该消息。

我通过将变量声明移动到函数顶部来解决这个问题。

作为参考,我正在 QtCreator 4.1.0 中使用 gdb 版本 7.11.1 进行测试,并使用 g++ 版本 5.4.1 进行编译

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.)

Naturally, you shouldn't have uninitialized variables, but in my case gdb attempts to show function local variables even before they are declared/initialized.

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.

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

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