Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Warning: Can't find linker symbol for virtual table for value XXX value" using GCC and GDB (CodeBlocks)

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.

like image 236
Heathcliff Avatar asked Jan 01 '12 20:01

Heathcliff


2 Answers

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.
like image 197
hmjd Avatar answered Oct 21 '22 17:10

hmjd


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

like image 39
sage Avatar answered Oct 21 '22 17:10

sage