I'm having trouble producing a test case that causes this problem
(I'm trying to narrow down a complex case that I have from copyrighted
code that I can't send out), but the general case is that I have a
parent template class that is a map. It defines virtual methods for
things like its hash function.
Then, there is a subclass that partially resolves the template to
have 'const char *' for keys and also defines the virtual methods
(including the hash method). The subclass header also has an inline
definition of the virtual hash function.
Now, when I go to do a lookup, I crash in some code that looks like
it is trying to load a function pointer from a vtable (but presumably
there isn't any vtable due to all the virtual methods being inlined).
I'm attaching a simplified version of the code that I'd hoped would
reproduce the problem, but doesn't (just to clarify what I'm talking
about).
Before I spend a bunch of time tracking this down -- is this a known
problem? Can anyone suggest a workaround ... maybe I can make all the
virtual methods non-inline, but I'm not convinced of that since it may
not be able to compile the code w/o knowing all the types involved (I'm
not a C++ expert by any stretch).
I'm building my test case as follows (which corresponds to who my
real case is being build)
/usr/bin/gcc3 -c -x c++ -O0 -fno-inline-functions -Wall -DDEBUG -g
test.h -o /tmp/dummy --dump-pch test-ppc.pfe
c++ -O0 -fno-inline-functions -Wall -DDEBUG -g --load-pch test-ppc.pfe
test.cpp -o test
#ifndef __TEST_H__
#define __TEST_H__
#include <stdio.h>
//
// Map
//
template <class TKEY, class TVAL> class Map
{
public:
Map();
virtual ~Map();
bool get(TKEY key, TVAL& val) const;
protected:
virtual unsigned int KeyToHashIndex(TKEY key) const;
};
template <class TKEY, class TVAL> inline
bool Map<TKEY, TVAL>::get(TKEY key, TVAL& val) const
{
unsigned int uiIndex = KeyToHashIndex(key);
fprintf(stderr, "uiIndex = 0x%08x\n", uiIndex);
return false;
}
template <class TKEY, class TVAL> inline
Map<TKEY, TVAL>::Map()
{
}
//---------------------------------------------------------------------------
template <class TKEY, class TVAL> inline
Map<TKEY, TVAL>::~Map()
{
}
template <class TKEY, class TVAL> inline
unsigned int Map<TKEY, TVAL>::KeyToHashIndex(TKEY key) const
{
return 0xdeadbeef;
}
//
// StringMap
//
template <class TVAL> class StringMap : public Map<const char *, TVAL>
{
public:
StringMap();
virtual ~StringMap();
protected:
virtual unsigned int KeyToHashIndex(const char* pcKey) const;
};
template <class TVAL> inline
StringMap<TVAL>::StringMap() :
Map<const char*, TVAL>()
{
}
template <class TVAL> inline
StringMap<TVAL>::~StringMap()
{
}
template <class TVAL> inline
unsigned int StringMap<TVAL>::KeyToHashIndex (const char* pKey) const
{
return 0xcafefeed;
}
#endif // __TEST_H__
#include "test.h"
int main(int argc, char *argv[])
{
StringMap<int> x;
int val;
const char *key = "";
x.get(key, val);
return 0;
}
-tim