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

27,686

Solution 1

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.

Solution 2

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

Share:
27,686
Heathcliff
Author by

Heathcliff

Updated on July 09, 2022

Comments

  • Heathcliff
    Heathcliff almost 2 years

    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.

  • Heathcliff
    Heathcliff over 12 years
    I chanched the attribute "proovedor" to string and it works. Thanks, I'm just making the migration from C to C++, so I'm accoustumed to build everything up from scratch, and didn't considered that the pointer to char may have being causing troubled.
  • MrMas
    MrMas about 8 years
    So what you're saying is that, in general, if the stated error is occurring, you're likely over-stepping memory bounds.