2011-09-01 244 views
3

我正在研究一個現有的數據解析程序,它將一個結構覆蓋到一個緩衝區中以提取值。最近一種新的數據格式已被添加到緩衝區,並需要一個新的結構。我抽象功能集成到一個公共的基類,並定義了新的結構是這樣的:C++訪問衝突

struct Header 
{ 
    Header() { } 

public: 
    virtual unsigned __int8 getCommonField1() const = 0; 
} 

struct HeaderTypeA : public Header 
{ 
    unsigned __int8 Field1; 

public: 
    unsigned __int8 getCommonField1() const { return Field1; } 
} 

struct HeaderTypeB : public Header 
{ 
    unsigned __int8 Field0; 
    unsigned __int8 Field1; 

public: 
    unsigned __int8 getCommonField1() const { return Field1; } 
} 

現有代碼它執行處理計算的數據(這是工作),並返回一個指針到調用函數...一些像這樣:

Header* parse() 
{  
    Header* parsedHeader = 0; 

    if (typeADetected) 
    { 
     parsedHeader = (HeaderTypeA *) &buffer[offset]; 
     // Other logic here... 
    } 
    else if (typeBDetected) 
    { 
     parsedHeader = (HeaderTypeB *) &buffer[offset]; 
     // Other logic here... 
    } 

    return (parsedHeader); 
} 

問題出現在解析邏輯的調用者。當插頭被返回作爲一個指針成員函數調用導致訪問衝突錯誤:

Header * hdr; 
hdr = m_parser->parse(); 
unsigned __int8 value = hdr->getCommonField1(); // Access Violation 

我實現上述代碼段缺少空指針檢查;爲了簡潔,我已經排除了一些這種邏輯。我已經追蹤了代碼,並且在嘗試調用基類上的方法之前,所有內容都可以順利運行。在玩代碼時,我也看到成員函數不存在錯誤。

感謝您的任何幫助。

+0

你能告訴我們初始化緩衝區嗎? – JaredPar

+0

什麼是「緩衝區」? –

+0

不幸的是,這並不容易。緩衝區實際上是作爲另一個結構的一部分傳遞給解析函數的。它的初始化深埋在我不敢觸及的一些C++代碼的深處。我應該注意到,我簡化了上面代碼片段的代碼。 – bporter

回答

5

您似乎在使用buffer中的存儲器而無需在其中構建對象。由於Header是多態的,它包含一個虛擬表格指針,你不能直接初始化它的數據(在法律上你不能,即使它是一個POD,但你可能會逃避它)。

您應該使用placement new以構建buffer中的Header對象。

parsedHeader = new (&buffer[offset]) HeaderTypeA; 
+2

+1這可能是墜機的原因。但是,虛擬功能表本身佔用空間,所以他會覆蓋標題中的前幾個字段。最好不要在這個應用程序中使用虛擬繼承。 –

+0

新的位置修復了訪問衝突,但我也沒有考慮到結構中vTable的影響。很好的答案,謝謝! – bporter

+0

@Amardeep虛擬函數表並不駐留在每個實例中,你的意思是虛擬函數指針嗎?無論如何,我假設他用'sizeof HeaderTypeX'更新'offset'。這裏也有對齊問題,在我的回答中我沒有涉及到。順便說一句,這不是虛擬繼承。 – Motti