2013-04-27 4 views
1

Я получаю странный сбой в конструкторе класса, который не изменился совсем недавно. Я обрезается прочь много вещей, но вот суть его:Сбой виртуальной таблицы 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 не обнаружил никаких повреждений.

+0

Моей ставкой было бы что-то тонкое изменение определения класса в одном файле, где оно включено, в сравнении с тем, как оно понимается в другом файле. Ошибки в макросах могут сделать это для вас, если вы измените заказ включения или включите разные заголовки, прежде чем включать заголовок с классом в нем. Это приводит к тому, что один кусок кода ожидает, что vtable отличается от другой сборки. –

+1

@david: Я подумал об этом и разделил класс на определение и реализацию, а затем переместил defn в начало файла. Так что он определяется сразу после заголовка, который определяет базовый класс. И угадай что? Нет крушения ... так что теперь мне просто нужно продолжать перемещать его ниже следующих заголовков/профилей, пока он не рухнет, а затем я изолировал определение изгоев. Благодарю. – fret

+0

Далее дальнейшее исследование показывает, что есть два класса с одним и тем же именем, один в главном приложении, а другой - в частной структуре. Так или иначе, компилятор не отмечает этого и не залог с ошибкой или работает правильно, несмотря на это. – fret

ответ

0

«Ответ» заключается в том, что в разных двоичных файлах было два класса с одинаковым именем. Один в исполняемом файле и один в частной структуре, который загружает exe. Так или иначе компилятор/компоновщик в XCode 4.5 не может обнаружить это и не связывать или загружать процесс. Visual Studio/Windows управляет этим штрафом по любой причине.

Итак, я переименовал класс в приложение, и он работает нормально. sigh

Предложение Дэвида использовать cppcheck или подобные звуки, как хороший долгосрочный совет.

Смежные вопросы