2014-08-27 102 views
0

我有一個名爲SFrame的結構,其中包含許多元素,值得注意的是2個無符號字符*類型的元素。我在我的類中創建了這個結構體的成員變量,但是我在我的類的某個函數的每次迭代中重新初始化它(除了某個布爾值爲true時)。我這樣做以下列方式:由於複製構造函數/刪除數組而導致內存損壞?

if (false == m_bRemainderNeedsProcessing) 
{ 
    // ... calls before and after the initialization are unimportant and not shown 
    m_sFrame = SFrame(); 
} 

然後我通過m_sFrame到一個函數來分配一些其元素的,然後我需要在我的結構分配一個無符號字符陣列到我pszMessage變量。

  m_sFrame.iMessageSize = m_sFrame.iPayloadLength; 
      m_sFrame.iOriginalMessageSize = m_sFrame.iPayloadLength; 
      m_sFrame.pszMessage = new unsigned char[m_sFrame.iPayloadLength + Constants::RSSL_DECODE_PADDING]; 
      m_sFrame.pszOriginalMessage = new unsigned char[m_sFrame.iPayloadLength + Constants::RSSL_DECODE_PADDING]; 

這些SFrame實例存儲在S幀的載體,即

std::vector<SFrame>; 

我希望能夠重用m_sFrame每次迭代,但我保證,如果我要清除內容的SFrame,當我將它存儲在矢量中時,SFrame被複制到矢量中而不會丟失它的指定值。爲此,我爲SFrame創建一個複製構造函數:

我附加了SFrame複製構造函數的一部分圖像。

ClearMemory(m_sFrame.pszMessage); 

凡ClearMemory函數執行以下操作:

在我的函數結束時,我做了以下明確的pszMessage內存(並且是幾乎相同的pszOriginalMessage)

void CPCAPParser::ClearMemory(unsigned char *pszBuffer) 
{ 
    if(pszBuffer != NULL) 
    { 
     delete [] pszBuffer; 
    } 
} 

禰的問題是,這個功能似乎被刪除超過了它應該做的....因爲多次迭代後,我得到一個未處理的異常:訪問衝突......

我附上了幾張可能有助於傳達問題的圖像。真的需要這個:(幫助,如果有人需要我補充更多的細節讓我知道

感謝

http://imageshack.com/f/pduGDLGZp(常量:: RSSL_DECODE_PADDING長度爲7,有13個字節總數已設置 - 。在內存塊的開始)

http://imageshack.com/f/exRaaEmip取得明顯 - 當我打電話ClearMemory(內存地址顯然仍然是相同的)

我會發布更多的圖像,但我沒有足夠的代表。 ...

SFrame:

struct SFrame 
{ 
    int* ipTemp_int_ptr; 
    int* ipTemp_int_ptr_actual; 
    int* piTimestampPos; 
    int* piOffset; 
    int iIP_Header_Length; 
    int iTCP_Header_Length; 
    int iTCP_Source_Port; 
    int iTCP_Dest_Port; 
    long long uiSequenceNumber; 
    long long uiInitialSequenceNumber; 
    long long uiAckNumber; 
    int iIp_total_length; 
    int iActual_frame_length; 
    int iOriginal_frame_length; 
    int iCaptured_frame_length; 
    int iTotalPayloadLength; 
    int iTotalMsgLoad; 
    int iPayloadLength; 
    int iBytesComplete; 
    int iFragmentID; 
    int iRemainder; 
    int iMessageSize; 
    int iOriginalMessageSize; 
    long long iNextExpectedSequenceNum; 
    std::string strSourceAddress; 
    std::string strDestAddress; 
    std::string strTimestamp; 
    unsigned char* pszMessage; 
    unsigned char* pszOriginalMessage; 
    unsigned int uiClientID; 
    int iStartOfRemainder; 
    int iAccumulatedMsgLength; 

    SFrame() : ipTemp_int_ptr (NULL), 
     ipTemp_int_ptr_actual (NULL), 
     piTimestampPos (NULL), 
     piOffset (NULL), 
     pszMessage (NULL), 
     pszOriginalMessage (NULL), 
     iIP_Header_Length(0), 
     iTCP_Header_Length (0), 
     iTCP_Source_Port (0), 
     iTCP_Dest_Port (0), 
     iIp_total_length (0), 
     iActual_frame_length (0), 
     iOriginal_frame_length (0), 
     iCaptured_frame_length (0), 
     uiSequenceNumber(0), 
     uiInitialSequenceNumber (0), 
     uiAckNumber(0), 
     iPayloadLength (0), 
     iNextExpectedSequenceNum (0), 
     uiClientID (0), 
     iMessageSize (0), 
     iOriginalMessageSize (0), 
     iFragmentID(0), 
     iTotalPayloadLength(0), 
     iBytesComplete(0), 
     iAccumulatedMsgLength (0), 
     iRemainder (0), 
     iStartOfRemainder(0), 
     iTotalMsgLoad (0) 
    { 
    } 

    SFrame(const SFrame &c_rSrc) 
    { 
     *this = c_rSrc; 
    } 

    SFrame &SFrame::operator=(const SFrame &c_rSrc) 
    { 
     iIP_Header_Length = c_rSrc.iIP_Header_Length; 
     iTCP_Header_Length = c_rSrc.iTCP_Header_Length; 
     iTCP_Source_Port = c_rSrc.iTCP_Source_Port; 
     iTCP_Dest_Port = c_rSrc.iTCP_Dest_Port; 
     iIp_total_length = c_rSrc.iIp_total_length; 
     iActual_frame_length = c_rSrc.iActual_frame_length; 
     iOriginal_frame_length = c_rSrc.iOriginal_frame_length; 
     iCaptured_frame_length = c_rSrc.iCaptured_frame_length; 
     iPayloadLength = c_rSrc.iPayloadLength; 
     uiSequenceNumber = c_rSrc.uiSequenceNumber; 
     uiInitialSequenceNumber = c_rSrc.uiInitialSequenceNumber; 
     uiAckNumber = c_rSrc.uiAckNumber; 
     iNextExpectedSequenceNum = c_rSrc.iNextExpectedSequenceNum; 
     uiClientID = c_rSrc.uiClientID; 
     iFragmentID = c_rSrc.iFragmentID; 
     iMessageSize = c_rSrc.iMessageSize; 
     iOriginalMessageSize = c_rSrc.iOriginalMessageSize; 
     iTotalPayloadLength = c_rSrc.iTotalPayloadLength; 
     iBytesComplete = c_rSrc.iBytesComplete; 
     iAccumulatedMsgLength = c_rSrc.iAccumulatedMsgLength; 
     iRemainder = c_rSrc.iRemainder; 
     iStartOfRemainder = c_rSrc.iStartOfRemainder; 
     iTotalMsgLoad = c_rSrc.iTotalMsgLoad; 

     strSourceAddress = c_rSrc.strSourceAddress; 
     strDestAddress = c_rSrc.strDestAddress; 
     strTimestamp = c_rSrc.strTimestamp; 

     pszMessage = (c_rSrc.pszMessage == NULL) ? NULL : new unsigned char[c_rSrc.iMessageSize]; 
     pszOriginalMessage = (c_rSrc.pszOriginalMessage == NULL) ? NULL : new unsigned char[c_rSrc.iOriginalMessageSize]; 

     if(pszMessage != NULL) 
     { 
      memcpy(pszMessage, c_rSrc.pszMessage, c_rSrc.iMessageSize); 
     } 


     if(pszOriginalMessage != NULL) 
     { 
      memcpy(pszOriginalMessage, c_rSrc.pszOriginalMessage, c_rSrc.iOriginalMessageSize); 
     } 

     return *this; 
    } 

    ~SFrame() 
    { 
     delete [] pszMessage; 
     delete [] pszOriginalMessage; 
    } 
}; 
+0

爲什麼這些成員指針而不是'std :: vector '? – PaulMcKenzie 2014-08-27 23:15:44

+0

http://imageshack.com/f/idjwk2pEp – 2014-08-27 23:16:05

+0

哪位成員Paul?... – 2014-08-27 23:17:19

回答

0

你的問題是,你的SFrame結構是不是安全asignable,但你把這個情況在std::vector,這將使副本。

或者:

  1. 添加工作用戶定義的拷貝構造函數和賦值運算符你SFrame結構或
  2. std::vector更換指針成員。

現在你的結構中有很多成員。如果您在複製構造函數中只錯過一個,或者您處理分配的內存有問題,那麼您將擁有一個損壞的副本。由於vector<SFrame>將創建副本,因此打破副本是vector<SFrame>的禁止發佈。

所以不是這樣,這裏是使用選項2的修補程序:

#include <vector> 
struct SFrame 
{ 
    std::vector<int> ipTemp_int_ptr; 
    std::vector<int> ipTemp_int_ptr_actual; 
    std::vector<int> piTimestampPos; 
    std::vector<int> piOffset; 
    int iIP_Header_Length; 
    int iTCP_Header_Length; 
    int iTCP_Source_Port; 
    int iTCP_Dest_Port; 
    long long uiSequenceNumber; 
    long long uiInitialSequenceNumber; 
    long long uiAckNumber; 
    int iIp_total_length; 
    int iActual_frame_length; 
    int iOriginal_frame_length; 
    int iCaptured_frame_length; 
    int iTotalPayloadLength; 
    int iTotalMsgLoad; 
    int iPayloadLength; 
    int iBytesComplete; 
    int iFragmentID; 
    int iRemainder; 
    int iMessageSize; 
    int iOriginalMessageSize; 
    long long iNextExpectedSequenceNum; 
    std::string strSourceAddress; 
    std::string strDestAddress; 
    std::string strTimestamp; 
    std::vector<unsigned char> pszMessage; 
    std::vector<unsigned char> pszOriginalMessage; 
    unsigned int uiClientID; 
    int iStartOfRemainder; 
    int iAccumulatedMsgLength; 

    SFrame() : 
     iIP_Header_Length(0), 
     iTCP_Header_Length (0), 
     iTCP_Source_Port (0), 
     iTCP_Dest_Port (0), 
     iIp_total_length (0), 
     iActual_frame_length (0), 
     iOriginal_frame_length (0), 
     iCaptured_frame_length (0), 
     uiSequenceNumber(0), 
     uiInitialSequenceNumber (0), 
     uiAckNumber(0), 
     iPayloadLength (0), 
     iNextExpectedSequenceNum (0), 
     uiClientID (0), 
     iMessageSize (0), 
     iOriginalMessageSize (0), 
     iFragmentID(0), 
     iTotalPayloadLength(0), 
     iBytesComplete(0), 
     iAccumulatedMsgLength (0), 
     iRemainder (0), 
     iStartOfRemainder(0), 
     iTotalMsgLoad (0) 
    { 
    } 
}; 

注意,拷貝構造函數和賦值運算符(和析構函數),現在都沒有了,從而使代碼更容易處理,並且在複製期間沒有機會錯過任何成員。相反,我們讓編譯器生成副本,編譯器將始終獲取每個成員複製。

現在,使用該結構的代碼庫必須重新編譯,並且不可避免地會出現編譯器錯誤。但是這些錯誤通常很容易修復。最有可能會要求你

  1. delete [] somepointer;刪除線,其中somePointer現在是一個載體,
  2. 如果指針傳遞到緩衝區的開頭,你通過&vector[0]vector.data(),因爲載體基本上是一個包裝爲new[]/delete[]

回到你原來的代碼,你賦值運算符的一個問題是你沒有刪除以前分配的內存,因此你有內存泄漏。此外,鑑於您編寫複製操作的方式,您沒有檢查自我分配。但是,這可能不是唯一的錯誤,因爲我們沒有看到你如何使用這些實例。

因此,更改爲向量,修復編譯器錯誤,重建和測試應用程序可能會更好。

+0

如果我想要添加一些數據在某個位置的矢量?我應該手動記錄正確的尺寸?數據塊中將有空值,但需要整個塊的大小。 – 2014-08-27 23:57:26

+0

@PatriciaAydin使用'vector :: insert'。 – PaulMcKenzie 2014-08-28 00:01:55

+0

但是確定尺寸? myvector.size()會讓我回到塊的大小,即使它有空終止字符?或者是矢量如何確定大小。如果是這樣,我會保持像我已經做過的手動尺寸 – 2014-08-28 00:03:12