2013-04-27 2 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.h, GTableLayout.cpp
- GCss.h, GCss.cpp

는 지금은 꽤 붙어
: 당신은 여기에서 볼 수 있도록 오픈 소스입니다. 나는 다음에 무엇을 시도해야할지 모른다. 그것은 정말 GCss 현재 클래스와는 아무 상관이없는 GDom 클래스와 뭔가를하고있는 것 같다

#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 

: 같은 오 스택 보인다. 컴파일러 버그 같은 냄새가 나지만 결론을 내리고 싶지는 않습니다. Valgrind는 부패를 일으키지 않았습니다.

+0

내 생각 엔 뭔가 포함될 수있는 클래스 파일 정의와 다른 파일에서 이해되는 클래스 정의를 미묘하게 변경하는 것이 겠지요. 매크로의 버그는 포함 순서를 변경하거나 클래스가 포함 된 헤더를 포함하기 전에 다른 헤더를 포함하는 경우이를 수행 할 수 있습니다. 이로 인해 하나의 코드가 다른 빌드와 다른 vtable을 기대하게됩니다. –

+1

@ david : 나는 그것에 대해 생각하고 클래스를 정의와 구현으로 분리 한 다음 defn을 파일의 맨 위로 옮겼습니다. 그래서 기본 클래스를 정의하는 헤더 바로 뒤에 정의되어 있습니다. 그리고 어떻게 됐을 까? 충돌이 없으므로 이제 충돌이 발생할 때까지 다음 헤더/데포를 지나쳐야합니다. 그런 다음 불량 정의를 격리했습니다. 감사. – fret

+0

더 자세히 조사해 보면 같은 이름을 가진 두 개의 클래스가 있다는 것을 알 수 있습니다. 하나는 기본 App에 있고 다른 하나는 개인 프레임 워크에 있습니다. 어떻게 든 컴파일러는 플래그를 지정하지 않고 오류가 발생하거나 올바르게 작동합니다. – fret

답변

0

"답"은 서로 다른 바이너리에 같은 이름을 가진 두 개의 클래스가 있다는 것입니다. 하나는 실행 파일에 있고, 하나는 개인 프레임 워크에서 exe가로드하는 것입니다. 어떻게 든 Xcode 4.5에서 컴파일러/링커는이를 감지하지 못해 프로세스를 연결하거나로드하지 못합니다. Visual Studio/Windows는 어떤 이유에서든이 벌금을 관리합니다.

그래서 앱의 클래스 이름이 바뀌었고 제대로 실행 중입니다. 한숨

좋은 장기적인 조언처럼 cppcheck 또는 유사한 소리를 사용하는 David의 제안.