Я получаю странный сбой в конструкторе класса, который не изменился совсем недавно. Я обрезается прочь много вещей, но вот суть его:Сбой виртуальной таблицы C++ LLVM/XCode
#define Accessor(PropName, Type, Default) \
Type PropName() { Type *Member = (Type*)Props.Find(Prop##PropName); \
if (Member) return *Member; \
return Default; } \
void PropName(Type t) { Type *Member = (Type*)Props.Find(Prop##PropName); \
if (Member) *Member = t; \
else { Props.Add(Prop##PropName, Member = new Type); \
*Member = t; } \
OnChange(Prop##PropName); }
class GCss
{
GHashTbl<int, void*> Props;
public:
virtual ~GCss() {}
virtual void OnChange(PropType p) {}
Accessor(TextAlign, Len, Len()); // and lots of others obviously
};
class GDom : virtual public GDomI
{
public:
virtual ~GDom() {}
virtual bool GetVariant(const char *Name, GVariant &Value, char *Array = 0) { return false; }
virtual bool SetVariant(const char *Name, GVariant &Value, char *Array = 0) { return false; }
};
class GLayoutCell : public GDom, public GCss
{
public:
};
class TableCell : public GLayoutCell
{
public:
TableCell(GTableLayout *t, int Cx, int Cy)
{
TextAlign(AlignLeft); // this call crashes trying to call 'OnChange'
}
};
Оказывается, что указатель метод OnChange в виртуальные таблицы является NULL. Теперь я сделал много вещей, чтобы попытаться проверить, что я не делаю что-то глупое. Восстановленный код с нуля в XCode 4.5 с использованием довольно стандартных настроек проекта, также попытался XCode 3.x с аналогичными результатами. Я пробовал наследовать тестовый объект от GLayoutCell и не получил никакого сбоя. Сама авария находится в частной структуре Lgi. Это с открытым исходным кодом, так что вы можете смотреть на него здесь:
- GDom.h
- GTableLayout.h, GTableLayout.cpp
- GCss.h, GCss.cpp
Я довольно застрял в настоящее время. Я не знаю, что попробовать дальше. О стек выглядит следующим образом:
#0 0x00341880 in typeinfo for GDom()
#1 0x00252698 in TableCell::TableCell(GTableLayout*, int, int) at /Users/matthew/Code/Lgi/trunk/src/mac/carbon/../../common/Widgets/GTableLayout.cpp:394
#2 0x0024d9cb in GTableLayout::GetCell(int, int, bool, int, int) at /Users/matthew/Code/Lgi/trunk/src/mac/carbon/../../common/Widgets/GTableLayout.cpp:1562
#3 0x0023f8eb in GProgressPane::GProgressPane() at /Users/matthew/Code/Lgi/trunk/src/mac/carbon/../../common/Widgets/GProgressDlg.cpp:129
#4 0x00241ff8 in GProgressDlg::Push() at /Users/matthew/Code/Lgi/trunk/src/mac/carbon/../../common/Widgets/GProgressDlg.cpp:407
#5 0x00241fb8 in GProgressDlg::OnCreate() at /Users/matthew/Code/Lgi/trunk/src/mac/carbon/../../common/Widgets/GProgressDlg.cpp:366
кажется, что-то делать с классом GDom, который на самом деле не имеет ничего общего с текущим классом ГКС. Меня пахнет ошибкой компилятора, но я не хочу делать выводы. Btw Valgrind не обнаружил никаких повреждений.
Моей ставкой было бы что-то тонкое изменение определения класса в одном файле, где оно включено, в сравнении с тем, как оно понимается в другом файле. Ошибки в макросах могут сделать это для вас, если вы измените заказ включения или включите разные заголовки, прежде чем включать заголовок с классом в нем. Это приводит к тому, что один кусок кода ожидает, что vtable отличается от другой сборки. –
@david: Я подумал об этом и разделил класс на определение и реализацию, а затем переместил defn в начало файла. Так что он определяется сразу после заголовка, который определяет базовый класс. И угадай что? Нет крушения ... так что теперь мне просто нужно продолжать перемещать его ниже следующих заголовков/профилей, пока он не рухнет, а затем я изолировал определение изгоев. Благодарю. – fret
Далее дальнейшее исследование показывает, что есть два класса с одним и тем же именем, один в главном приложении, а другой - в частной структуре. Так или иначе, компилятор не отмечает этого и не залог с ошибкой или работает правильно, несмотря на это. – fret