2014-08-27 5 views
0

많은 요소, 특히 unsigned char * 유형의 요소가 두 개 포함 된 SFrame이라는 구조체가 있습니다. 내 클래스 에서이 구조체의 멤버 변수를 만들지 만, 새로 추가 된 클래스의 함수에서 각 반복마다 (특정 부울이 참일 때를 제외하고) 새로 초기화합니다. 요소의 일부를 할당하는 함수에 복사 생성자/배열 삭제로 인한 메모리 손상?

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 인스턴스

std::vector<SFrame>; 

내가 각 반복에 대한 m_sFrame를 재사용 할 수 있도록하려면 즉 SFrames의 벡터에 저장하지만 난 내용을 지우려고하면되도록해야 SFrame을 벡터 안에 저장하면 SFrame은 할당 된 값을 잃지 않고 벡터에 복사됩니다. 이를 위해 SFrame의 복사 생성자를 만듭니다.

SFrame의 복사 생성자 이미지를 첨부했습니다. ClearMemory 기능은 다음 않는 경우

ClearMemory(m_sFrame.pszMessage); 

: 내 함수의 끝에

, 나는 다음을 수행하여 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

+0

http://imageshack.com/f/idjwk2pEp –

+0

어느 멤버 Paul ... ... –

답변

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) 
    { 
    } 
}; 

복사 생성자와 대입 연산자 (그리고 소멸자가) 이제 사라하는 것으로, 따라서 처리하기 위해 훨씬 더 쉽게 코드를 만들고, 복사하는 동안 회원 중 한 명이 누락 될 가능성도 없습니다. 대신 우리는 컴파일러가 복사를 생성하도록하고 컴파일러는 항상을 복사합니다.

이제 구조체를 사용하는 코드베이스를 다시 컴파일해야하고 필연적으로 컴파일러 오류가 발생합니다. 그러나 이러한 오류는 대개 수정하기가 쉽습니다. somePointer 지금은 벡터와

  • 벡터는 기본적으로이기 때문에 버퍼의 시작 부분에 대한 포인터를 전달하면, &vector[0] 또는 vector.data() 전달하는 경우이고 대부분은 아마 delete [] somepointer;으로 줄을 제거

    1. 당신이 필요합니다 new[]/delete[]에 대한 래퍼

    원래 코드로 돌아 가면 할당 연산자의 한 가지 문제는 할당 된 이전 메모리를 삭제하지 못했기 때문에 메모리 누수가 발생했기 때문입니다. 또한, 복사 작업을 작성한 방식을 고려할 때 자체 할당을 확인하지 않았습니다. 그러나이 오류가 유일한 오류 일 수는 없습니다. 이러한 SFrame 인스턴스를 사용하는 방법을 알지 못했기 때문입니다.

    따라서 벡터로 변경하고 컴파일러 오류를 수정하고 응용 프로그램을 다시 작성하고 테스트하는 것이 좋습니다.

  • +0

    벡터의 특정 위치에 데이터를 추가하고 싶다면 어떻게해야 하는가? ? 수동으로 크기를 추적해야합니까? 데이터 블록에는 null 값이 있지만 전체 블록의 크기가 필요합니다. –

    +0

    @PatriciaAydin'vector :: insert'를 사용하십시오. – PaulMcKenzie

    +0

    크기를 결정하는 것? myvector.size()는 null 문자로 종료 되었더라도 블록 크기를 돌려 줄까요? 또는 벡터가 크기를 결정하는 방법입니다. 그렇다면 나는 이미했던 것처럼 수동 크기를 유지할 것입니다. –