2017-11-23 6 views
0

코드를보고 몇 시간 동안 여기에 앉아 있습니다. 이해가 가지 않습니다. 그것은 약 std :: vector canData에 관한 것이고 이것은 CAN DBC 파서로부터 데이터를 디코딩하고 인코딩하기위한 버퍼로 사용됩니다. 내 문제의 전체 예제는 here.벡터에서 쓰기/읽기로 이상한 동작이 발생했습니다.

입니다. 기본적으로 배열에 인코딩 된 값이 있으며이 배열에서 다시 디코딩됩니다. 그러나이 배열의 크기는 항상 0이며 배열을 지운 후에도 0이더라도 배열로부터 데이터를 디코딩 할 수 있습니다.

누군가 나에게 설명해 줄 수 있습니까?
내가 뭔가를 놓친 건가요?

unsigned int canIdentifier = 0x100; 
std::vector<std::uint8_t> canData; 
canData.reserve(4); 
network.messages[canIdentifier].signals["multiplexor"].encode(canData, 0); 
network.messages[canIdentifier].signals["signal_1"].encode(canData, 0x12); 

std::cout << "size: " << canData.size() << std::endl; 

canData.clear(); 
decodeMessage(canIdentifier, canData); 
std::cout << "2size: " << canData.size() << std::endl; 

업데이트 필요 기능 :

uint64_t Signal::decode(std::vector<uint8_t> & data) 
{ 
/* safety check */ 
if (bitSize == 0) { 
    return 0; 
} 

/* copy bits */ 
uint64_t retVal = 0; 
if (byteOrder == ByteOrder::BigEndian) { 
    /* start with MSB */ 
    unsigned int srcBit = startBit; 
    unsigned int dstBit = bitSize - 1; 
    for (unsigned int i = 0; i < bitSize; ++i) { 
     /* copy bit */ 
     if (data[srcBit/8] & (1 << (srcBit % 8))) { 
      retVal |= (1ULL << dstBit); 
     } 

     /* calculate next position */ 
     if ((srcBit % 8) == 0) { 
      srcBit += 15; 
     } else { 
      --srcBit; 
     } 
     --dstBit; 
    } 
} else { 
    /* start with LSB */ 
    unsigned int srcBit = startBit; 
    unsigned int dstBit = 0; 
    for (unsigned int i = 0; i < bitSize; ++i) { 
     /* copy bit */ 
     if (data[srcBit/8] & (1 << (srcBit % 8))) { 
      retVal |= (1ULL << dstBit); 
     } 

     /* calculate next position */ 
     ++srcBit; 
     ++dstBit; 
    } 
} 

/* if signed, then fill all bits above MSB with 1 */ 
if (valueType == ValueType::Signed) { 
    if (retVal & (1 << (bitSize - 1))) { 
     for (unsigned int i = bitSize; i < 8 * sizeof(retVal); ++i) { 
      retVal |= (1ULL << i); 
     } 
    } 
} 

return retVal; 
} 

void Signal::encode(std::vector<uint8_t> & data, uint64_t rawValue) 
{ 
/* safety check */ 
if (bitSize == 0) { 
    return; 
} 

/* copy bits */ 
if (byteOrder == ByteOrder::BigEndian) { 
    /* start with MSB */ 
    unsigned int srcBit = startBit; 
    unsigned int dstBit = bitSize - 1; 
    for (unsigned int i = 0; i < bitSize; ++i) { 
     /* copy bit */ 
     if (rawValue & (1ULL << dstBit)) { 
      data[srcBit/8] |= (1 << (srcBit % 8)); 
     } else { 
      data[srcBit/8] &= ~(1 << (srcBit % 8)); 
     } 

     /* calculate next position */ 
     if ((srcBit % 8) == 0) { 
      srcBit += 15; 
     } else { 
      --srcBit; 
     } 
     --dstBit; 
    } 
} else { 
    /* start with LSB */ 
    unsigned int srcBit = startBit; 
    unsigned int dstBit = 0; 
    for (unsigned int i = 0; i < bitSize; ++i) { 
     /* copy bit */ 
     if (rawValue & (1ULL << dstBit)) { 
      data[srcBit/8] |= (1 << (srcBit % 8)); 
     } else { 
      data[srcBit/8] &= ~(1 << (srcBit % 8)); 
     } 

     /* calculate next position */ 
     ++srcBit; 
     ++dstBit; 
    } 
} 
} 
+1

아, 정의되지 않은 행동의 기쁨 ... 'enccode' 및'decodeMessage'에 대한 코드 없이는 더 이상 말할 수 없습니다. – 1201ProgramAlarm

+0

'reserve'와'resize'는 다릅니다. 벡터에서'reserve '를 호출 한 후에 크기는 변하지 않습니다. 기본으로 구성된'std :: vector'는 0 요소를 포함하므로'canData'는'encode'에서 사용될 때 여전히 0 요소를 포함합니다. 나는'encode'가 0보다 큰 크기의 버퍼를 기대한다고 가정합니다. 당신이 그 기능이하는 것을 공유하지 않았으므로 확실하게 말할 수는 없습니다. 'std :: vector :: reserve'는 대개 후속 삽입의 성능을 향상시키는 데 사용됩니다. –

+0

'canData.reserve (4);'- 거기에'reserve()'대신'resize()'를 쓰고 싶다고 생각합니다. 'reserve()'는 예약 된 메모리에 쓸 수있는 권한을주지 않습니다. –

답변

1

단계에서 코드 스텝 상대 :

canData.reserve(4); 

는 (적어도) 4 uint8_t 포함될 수 벡터에 대해 메모리를 할당하지만 0을 포함합니다 (canData.resize (4)는 벡터 크기를 변경합니다). canData.capacity()는 4 이상이지만 canData.size()는 0입니다.

연산자 ([...]를 사용하여 encode (...) 메소드 액세스 벡터를 사용합니다. 인덱스가 범위 내에 있는지 (canData.size()보다 작 으면) 검사하지 않으므로 예외 (vector at()가 사용 된 경우)가 throw됩니다. 또한 액세스 된 인덱스가 할당 된 메모리에 있기 때문에 나쁜 (특히 메모리 누수) 것도 발생하지 않습니다.

범위 내의 모든 벡터 요소를 삭제하고 인덱스 0과 canData.size() 사이를 삭제합니다. 따라서 canData.size() 위의 요소에는 영향을 미치지 않으며,이 경우 0입니다. clear()는 vector에 할당 된 메모리를 줄이지도 않는다. 메모리를 줄이기 위해 재 할당 할 수도 없다. - shrink_to_fit()는 그렇게 할 것이다.

결국 decodeMessage는 파괴되지 않은 올바른 데이터로 할당되고 채워지는 메모리에서 작동합니다. 다시 벡터 연산자 []를 사용하면 예외/메모리 누수가 발생하지 않습니다.

댓글에 명시된 바와 같이 정의되지 않은 동작이 많습니다.

관련 문제