2013-04-27 50 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' 
    } 
}; 

看來,vtable中的OnChange方法指針爲NULL。現在我已經做了很多事情來檢查我是不是在做一些愚蠢的事情。使用相當默認的項目設置在XCode 4.5中重新構建代碼,也嘗試了XCode 3.x,並得到了類似的結果。我試過從GLayoutCell繼承一個測試對象,並沒有崩潰。崩潰本身位於名爲Lgi的私人框架中。它是開源的,所以你可以看看這裏:
- GDom.h
- GTableLayout.hGTableLayout.cpp
- GCss.hGCss.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類,它真的沒有任何與GCSS當前類的東西。聞起來像是一個編譯器bug,但我不想跳到結論。順便說一句Valgrind沒有發現任何腐敗。

+0

我敢打賭,它會在一個文件中微妙地改變它的類定義,而這個文件在另一個文件中被理解。如果您在包含頭文件之前更改包含順序或包含不同頭文件,則宏中的錯誤可以爲您執行此操作。這會導致一段代碼期望一個不同於另一個構建的vtable。 – 2013-04-27 07:40:47

+1

@david:我有一個想法,並將該類分成定義和實現,然後將defn移動到文件頂部。所以它是在定義基類的頭文件後面定義的。你猜怎麼着?沒有崩潰......所以現在我只需要繼續將它放在下面的頭部/ defns中,直到它崩潰,然後我隔離了流氓定義。謝謝。 – fret 2013-04-27 08:50:54

+0

好的進一步調查顯示,有兩個同名的類,一個在主App中,另一個在私有框架中。不知何故,編譯器不會標記這一點,或者保留一個錯誤或者正常工作。 – fret 2013-04-27 09:27:37

回答

0

「答案」是在不同的二進制文件中有兩個同名的類。一個在可執行文件中,另一個在exe文件加載的私有框架中。不知何故,XCode 4.5中的編譯器/鏈接器無法檢測到該鏈接或無法鏈接或加載進程。無論出於何種原因,Visual Studio/Windows都可以管理此罰款。

所以我重新命名了App中的類,它運行正常。 嘆息

大衛的建議使用cppcheck或類似的聲音,如良好的長期建議。