GDB warning: RTTI symbol not found for class

Started by
6 comments, last by smart_idiot 13 years ago
I use Eclipse with GDB. For any smart pointer class I have such as a MyString, I keep getting

warning: RTTI symbol not found for class MyString

And indeed, I can't see the value held by a smart pointer container:

MyString str = "test"; //can see "test" fine when examining variable value
MyStringPtr strPtr = &str; //can not see "test" contained by the container strPtr when examining variable value.

I figure the warning is the cause, that the pointer to "test" became a void pointer rather than a typed pointer of MyString. Nonetheless, this works:

int L = strPtr->length(); //correctly is 4
char c = strPtr->charAt(1); //correctly is 'e'.

So GDB seems to be handling things correctly, but not perfect so that I can't debug.

Figure would ask before posting else where.
Advertisement
Post your code for the faulting classes (both the string and smart pointers) as well as your complete compiler settings.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

I should mention there is no problem when developing in Visual Studio. Problem only occurs for Eclipse with Cygwin g++.

Cygwin g++ compile options:
-O0 -g3 -Wall -c -fmessage-length=0

Below is a simplified sketch of relevant classes.



class MyObjectPtr
{
protected:
MyObject* pObj;
public:

MyObjectPtr(MyObject* p= 0);
MyObjectPtr(const MyObjectPtr& r);

~MyObjectPtr();

protected:
void set(MyObject* p)
{
if(p!=0) p->incrementReference();
if(pObj!=0) pObj->decreasetReference();
pObj= p;
}
void set(const char* chArray)
{
pObj= new MyString(chArray);
if(pObj!=0) pObj->incrementReference();
}

void assertError(const char* error);
public:
const MyObjectPtr& operator=(const MyObjectPtr& r)
{
set(r); return *this;
}
const MyObjectPtr& operator=(MyObject* p)
{
set(p); return *this;
}

MyObject* operator->()
{
if(pObj==null) assertError("MyObject");
return pObj;
}

operator MyObject*() const { return pObj; };


MyObjectPtr(const char* pch)
{
set(pch);
};
const MyObjectPtr& operator=(const char* pch);
};


class MyStringPtr : public MyObjectPtr
{
public:
MyStringPtr(MyObject* p= 0) : MyObjectPtr(p) {}
MyStringPtr(const int n) : MyObjectPtr() {}

const MyStringPtr& operator=(MyObject* p)
{
set(p); return *this;
}
MyString* operator->()
{
if(pObj==null) assertError("MyString");
return (MyString*)pObj;
};

MyStringPtr(const char* pch)
{
if( pch != NULL )
{
set( new MyString(pch) );
}
else
set( NULL );
}

//other MyString related
};

class MyString : public MyObject
{
int length;
char* data;

void allocate(int iSize)
{
data= new char[iSize];
}

DString(const char* dataIn)
{
if(dataIn==0) assertError("NullString");
length= strlen(dataIn);
alloc(length+1);
memcpy(data, dataIn, length+1);
}
};


class DFC_DLL DObject
{
int referenceCount;

void incrementReference()
{
referenceCount++;
}
void decrementReference()
{
referenceCount--;
}
};

Your code has a number of serious flaws, ignoring the fact that you basically made it up on the fly and didn't post your real code. (There's all kinds of obvious mistakes in what you posted, beyond the deeper issues in the implementation, that make it pretty clear you just wrote that on the spot and it bears no real relation to your actual code. This is a very bad thing to do when asking for help. If my car broke down and I wanted you to help fix it, would it make sense for me to direct you to a bicycle in my garage to start investigating the problem? No. So don't do that.)

Look into RAII, exception safety, the rule of three, virtual destructors and why you need them, and memory leaks.


It looks to me like you might have some background in C# or even Java, and you're carrying over a lot of habits and assumptions from that language into C++. This is, in general, extremely dangerous and liable to produce a lot of very substandard code. Don't let the curly braces and semicolons fool you; C++ is a very different language and strictly demanding in many areas of discipline and attention to detail.

In this particular case it looks to me like your problem is a fairly straightforward beginner mistake in not understanding the way RTTI and type dispatches work in C++; I won't spoil it by giving you the answer, because then you'd be tempted to just add a couple minor tweaks to your code and move on without learning anything. Instead, I'll encourage you to do some research into the areas I listed above, and hopefully it should become clear after that what you're doing wrong.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Your intentions are good.

More importantly, do you mean GDB failing to know pointer type, as if the virtual function table doesn't exist, is due to 'not understanding the way RTTI and type dispatches work in C++'?

Might you have some hints on why without GDB the string memory is otherwise correctly accessible, albeit with leaks and other flaws?

How do you suggest I communicate better?
As often with software dev, the code is an inheritance. While needing improvement, I have no authority to post a direct copy of the code.

Moreover, to reach a wider audience, convoluted Mac/Windows defines, allocation alignments, hashing functions, macro expansions, and etc. had been removed to improve clarity.

More importantly, do you mean GDB failing to know pointer type, as if the virtual function table doesn't exist, is due to 'not understanding the way RTTI and type dispatches work in C++'?

Well, *cough*, do you have any virtual functions? Certainly you do not in the code you posted.

We can only guess vaguely if you only describe the problem vaguely. See if you can come up with a small compilable test program that produces the same behaviour.

Stephen M. Webb
Professional Free Software Developer


[quote name='rumble' timestamp='1302486090' post='4796900']
More importantly, do you mean GDB failing to know pointer type, as if the virtual function table doesn't exist, is due to 'not understanding the way RTTI and type dispatches work in C++'?

Well, *cough*, do you have any virtual functions? Certainly you do not in the code you posted.

We can only guess vaguely if you only describe the problem vaguely. See if you can come up with a small compilable test program that produces the same behaviour.
[/quote]

Ah they have been there. My mistake for not including the virtual destructors when simplifying the code.

Inspired from your comments, my problem can be illustrated with the following piece of code:


class A
{
int Aint;
public:
virtual ~A(){}
};
class B : public A
{
float Bfloat;
public:
virtual ~B(){}
};


int main(int argc, char* argv[])
{
A* pA;
pA = new B();

delete pA;
return 0;
}


In Eclipse with Cygwin g++ and gdb, mousing over pA I see member Aint. That's it.

In VS2008, mousing over pA I see member Aint. Additionally, I do see __vfptr, Bfloat.

Both IDE have default settings.

The former has compilation flag -O0 -g3 -Wall -c -fmessage-length=0. No "RTTI symbol not found for class" message is printed for this simple example.

Feel free to try.

[quote name='rumble' timestamp='1302486090' post='4796900']
More importantly, do you mean GDB failing to know pointer type, as if the virtual function table doesn't exist, is due to 'not understanding the way RTTI and type dispatches work in C++'?

Well, *cough*, do you have any virtual functions? Certainly you do not in the code you posted.

We can only guess vaguely if you only describe the problem vaguely. See if you can come up with a small compilable test program that produces the same behaviour.
[/quote]

Ah they have been there. My mistake for not including the virtual destructors when simplifying the code.

Inspired from your comments, my problem can be illustrated with the following piece of code:


class A
{
int Aint;
public:
virtual ~A(){}
};
class B : public A
{
float Bfloat;
public:
virtual ~B(){}
};


int main(int argc, char* argv[])
{
A* pA;
pA = new B();

delete pA;
return 0;
}


In Eclipse with Cygwin g++ and gdb, mousing over pA I see member Aint. That's it.

In VS2008, mousing over pA I see member Aint. Additionally, I do see __vfptr, Bfloat, and the B is derived from A relationship.

Both IDE have default settings.

The former has compilation flag -O0 -g3 -Wall -c -fmessage-length=0. No "RTTI symbol not found for class" message or any run time warning appears for this simple example.

Feel free to try.
The above code works for me, GDB says *pA = {_vptr.A = 0x89485ed18949ed31, Aint = -461158174},
and *(B*)pA = {<A> = {_vptr.A = 0x89485ed18949ed31, Aint = -461158174}, Bfloat = 869647}


My guess would be to use -ggdb3 rather than just -g3. I'm not really confident that'll fix your problem, but that's all I can think of.
Chess is played by three people. Two people play the game; the third provides moral support for the pawns. The object of the game is to kill your opponent by flinging captured pieces at his head. Since the only piece that can be killed is a pawn, the two armies agree to meet in a pawn-infested area (or even a pawn shop) and kill as many pawns as possible in the crossfire. If the game goes on for an hour, one player may legally attempt to gouge out the other player's eyes with his King.

This topic is closed to new replies.

Advertisement