2016-05-03 10 views
0

Problem ist:ungültige Zeiger beim Laufen Gtest

Fehler in `./runTests': frei(): ungültigen Zeigern: 0x00007fdb92fe27a0 Aborted

Testsuite ist:

#include "serial/BufferWrapper.h" 
#include <iostream> 
#include <memory> 
#include <gtest/gtest.h> 


#define STREAM_LEN 128 

using namespace std; 

namespace { 

// The fixture for testing class BufferWrapperTest. 
class BufferWrapperTest : public ::testing::Test 
{ 
public: 
    // Objects declared here can be used by all tests. 
    unique_ptr<serial::BufferWrapper> bw; 

    BufferWrapperTest() : 
     bw((unique_ptr<serial::BufferWrapper>) new serial::BufferWrapper()) 
    {} 

    //virtual ~BufferWrapperTest(){} 

    // If the constructor and destructor are not enough for setting up 
    // and cleaning up each test, you can define the following methods: 

    //virtual void SetUp() { 
     // Code here will be called immediately after the constructor (right 
     // before each test). 
    //} 

    //virtual void TearDown() { 
     // Code here will be called immediately after each test (right 
     // before the destructor). 
    //} 

}; // BufferWrapperTest 

/*! tests that checksum works in buffer wrapper */ 
TEST_F(BufferWrapperTest, CheckSum) { 

    std::vector<unsigned char> test_vec; 

    test_vec.push_back('0');  // us1 
    test_vec.push_back('0');  // us2 
    test_vec.push_back('0');  // ir1 
    test_vec.push_back('0');  // ir2 
    test_vec.push_back('0');  // ir3 
    test_vec.push_back('0');  // wheel 
    test_vec.push_back('0');  // dis1 
    test_vec.push_back('0');  // dis2 
    test_vec.push_back('0');  // dis3 
    test_vec.push_back('0');  // dis4 
    test_vec.push_back('0');  // light 

    ASSERT_EQ((unsigned char) 48, bw->checksum(test_vec)); 

    // clear after first test 
    test_vec.clear(); 

    test_vec.push_back('2');  // us1 
    test_vec.push_back('3');  // us2 
    test_vec.push_back('4');  // ir1 
    test_vec.push_back('5');  // ir2 
    test_vec.push_back('6');  // ir3 
    test_vec.push_back('0');  // wheel 
    test_vec.push_back('0');  // dis1 
    test_vec.push_back('0');  // dis2 
    test_vec.push_back('0');  // dis3 
    test_vec.push_back('0');  // dis4 
    test_vec.push_back('0');  // light 

    ASSERT_EQ((unsigned char) 54, bw->checksum(test_vec)); 
} 

int main(int argc, char **argv) { 
    ::testing::InitGoogleTest(&argc, argv); 
    return RUN_ALL_TESTS(); 
} 

Funktion checksum ist:

unsigned char serial::BufferWrapper::checksum(const std::vector<unsigned char> pkt) 
{ 
    unsigned char chksum = 0; 
    if (pkt.size() == 0) return chksum; 
    for (auto it = pkt.begin(); it != pkt.end(); ++it) { 
     // the checksum is calculated by XOR all elements 
     chksum = (unsigned char)(chksum^*it); 
    } 
    return chksum; 
} 

* EDIT: die

#include <iostream> 
#include <iomanip> 
#include <mutex> 
#include <algorithm> 
#include "serial/BufferWrapper.h" 
#include "containerfactory/SBDContainer.h" 

using namespace std; 

// append receive buffer mutex 
std::mutex arb; 
// append send buffer mutex 
std::mutex asb; 
// read send buffer mutex 
std::mutex rsm; 
// read receive buffer mutex 
std::mutex rrm; 

/*! constructor */ 
serial::BufferWrapper::BufferWrapper() : buffer_in({}), buffer_out({}) 
{ 
    cout << "creating buffer wrapper... "; 
    cout << "[OK]" << endl; 
} 


/*! destructor */ 
serial::BufferWrapper::~BufferWrapper() 
{ 
    cout << "destroying buffer wrapper... "; 
    cout << "[OK]" << endl; 
} 


/*! appends a correct packet to the receive buffer */ 
void serial::BufferWrapper::appendReceiveBuffer(vector<unsigned char> data) 
{ 
    // lock mutex 
    arb.lock(); 
    // return if the length of the vedcor is too short 
    if (data.size() < SBDPKTSIZE) { 
     // unlock mutex 
     arb.unlock(); 
     return; 
    } 
    // the vector to hold the correct packet 
    vector<unsigned char> valid_pkt; 
    // loop through the received data from the read and look 
    // for a correct packet 
    for (auto it = data.begin(); it != data.end(); it++) { 
     if (it + SBDPKTSIZE > data.end()) { 
      break; 
     } 
     if (*it == DEL_ONE && *(it+DEL_TWO_POS) == DEL_TWO && 
       *(it+DEL_DBCOLON_POS) == DEL_DBCOLON && *(it+DEL_COMMA_POS) == DEL_COMMA) { 
      unsigned char us1 = *(it+US1_POS); 
      //printf("US1:%i ", us1); 
      unsigned char us2 = *(it+US2_POS); 
      //printf("US2:%i ", us2); 
      unsigned char ir1 = *(it+IR1_POS); 
      //printf("IR1:%i ", ir1); 
      unsigned char ir2 = *(it+IR2_POS); 
      //printf("IR2:%i ", ir2); 
      unsigned char ir3 = *(it+IR3_POS); 
      //printf("IR3:%i ", ir3); 
      unsigned char wheel = *(it+WHL_POS); 
      //printf("WHEEL:%i ", wheel); 
      unsigned char dis1 = *(it+DIS_POS_1); 
      //printf("DIS1:%i ", dis1); 
      unsigned char dis2 = *(it+DIS_POS_2); 
      //printf("DIS2:%i ", dis2); 
      unsigned char dis3 = *(it+DIS_POS_3); 
      //printf("DIS3:%i ", dis3); 
      unsigned char dis4 = *(it+DIS_POS_4); 
      //printf("DIS4:%i ", dis4); 
      unsigned char light = *(it+LIGHT_SEN); 
      //printf("LIGHT:%i ", light); 
      unsigned char check = *(it+CHK_SUM); 
      //printf("CHECK:%i\n", check); 
      // fill the vector 
      valid_pkt = {us1, us2, ir1, ir2, ir3, wheel, dis1, dis2, dis3, dis4, light}; 
      // check if correct checksum 
      if (check == checksum(valid_pkt)) { 
       cout << "checksum OK" << endl; 
       break; 
      } 
      else { 
       cout << "checksum FAIL" << endl; 
       // clear the return vector 
       valid_pkt.clear(); 
       // find where next packet starts 
       it = find(it+1, data.end(), DEL_ONE); 
       // if not found, break 
       if (it == data.end()) break; 
      } 
     } 
    } 
    // push in front of the buffer if valid data 
    if (valid_pkt.size() != 0) { 
     buffer_in.push_front(valid_pkt); 
    } 
    // unlock mutex 
    arb.unlock(); 
} 


/*! returns the most recent valid packet from the read buffer */ 
vector<unsigned char> serial::BufferWrapper::readReceiveBuffer(void) 
{ 
    rrm.lock(); 
    // check for size, i.e. not empty 
    if(buffer_in.size() != 0) 
    { 
     // get 3the most recent packet, always in first position 
     std::vector<unsigned char> vec = buffer_in.at(0); 
     // clear the buffer 
     buffer_in.clear(); 
     rrm.unlock(); 
     return vec; 
    } 
    else 
    { 
     rrm.unlock(); 
     return {}; 
    } 
} 


/*! appends a correct packet to the send buffer */ 
void serial::BufferWrapper::appendSendBuffer(vector<unsigned char> vec) 
{ 
    // lock mutex 
    asb.lock(); 
    buffer_out.push_front(vec); 
    // and unlock after append 
    asb.unlock(); 
} 


/*! returns the most recent valid packet from the send buffer */ 
vector<unsigned char> serial::BufferWrapper::readSendBuffer(void) 
{ 
    rsm.lock(); 
    // check for size, i.e. not empty 
    if(buffer_out.size() != 0) 
    { 
     // get the most recent packet, always in first position 
     vector<unsigned char> v = buffer_out.at(0); 
     // clear the buffer 
     buffer_out.clear(); 
     rsm.unlock(); 
     return v; 
    } 
    else 
    { 
     rsm.unlock(); 
     return {}; 
    } 
} 


/*! calculates and returns the checksum for a valid packet */ 
unsigned char serial::BufferWrapper::checksum(const std::vector<unsigned char> pkt) 
{ 
    unsigned char chksum = 0; 
    if (pkt.size() == 0) return chksum; 
    for (auto it = pkt.begin(); it != pkt.end(); ++it) { 
     // the checksum is calculated by XOR all elements 
     chksum = (unsigned char)(chksum^*it); 
    } 
    return chksum; 
} 

EDIT * serial::BufferWrapper Hinzugefügt hinzugefügt, um die Erklärung:

namespace serial 
{ 
    class BufferWrapper 
    { 
    public: 
     /*! constructor */ 
     BufferWrapper(); 
     /*! destructor */ 
     ~BufferWrapper(); 
     /*! appends data read from the serial to the receive buffer */ 
     void appendReceiveBuffer(std::vector<unsigned char>); 
     /*! returns a valid packet from the receive buffer */ 
     std::vector<unsigned char> readReceiveBuffer(void); 
     /*! appends to the send buffer data to write to the serial */ 
     void appendSendBuffer(std::vector<unsigned char>); 
     /*! returns a valid packet to write to the serial */ 
     std::vector<unsigned char> readSendBuffer(void); 
     /*! returns the checksum for a valid packet */ 
     unsigned char checksum(const std::vector<unsigned char>); 
    private: 
     /*! the receive buffer */ 
     std::deque<std::vector<unsigned char>> buffer_in; 
     /*! the send buffer */ 
     std::deque<std::vector<unsigned char>> buffer_out; 
    }; 
} 

Der vollständige Ausdruck aus der Durchführung des Tests ist:

[==========] Running 1 test from 1 test case. 
[----------] Global test environment set-up. 
[----------] 1 test from BufferWrapperTest 
[ RUN  ] BufferWrapperTest.CheckSum 
creating buffer wrapper... [OK] 
destroying buffer wrapper... [OK] 
[  OK ] BufferWrapperTest.CheckSum (1 ms) 
[----------] 1 test from BufferWrapperTest (1 ms total) 

[----------] Global test environment tear-down 
[==========] 1 test from 1 test case ran. (1 ms total) 
[ PASSED ] 1 test. 
*** Error in `./runTests': free(): invalid pointer: 0x00007fdb92fe27a0 *** 
Aborted 

, warum dies geschieht, wenn die Test läuft und vervollständigt und der Zeiger in der Testsuite wird erstellt und zerstört?

+1

Welche Plattform/Betriebssystem? Benutze Valgrind? Wie sieht serial :: BufferWrapper aus? usw. – paulm

+0

OS ist Linux Mint. Der 'serial :: BufferWrapper' wurde hinzugefügt. – tik

+0

Der Fehler tritt auf ** nachdem ** Ihre gesamte Testsuite ausgeführt wurde. Versuchen Sie, die Test-Programmdatei in gdb auszuführen und sehen Sie, wie der Aufruf-Stack aussieht. –

Antwort

1

Ich würde wetten, dass das Problem dieser Initialisierung ist:

bw((unique_ptr<serial::BufferWrapper>) new serial::BufferWrapper()) 

Hier können Sie zuteilen ein serial::BufferWrapper Objekt, aber dann werfen Sie den Zeiger auf ein std::unique_ptr<...>Objekt, die der Compiler bedeutet rufen die std::unique_ptr<...>Bewegungconstructor. Der Konstruktor, der aufgerufen werden sollte, sollte derjenige sein, der einen Zeiger auf den umschlossenen Typ verwendet.

So lösen das Problem nur das Casting überspringen und hier

bw(new serial::BufferWrapper) 

Die Lektion tun? Um nie jemals verwenden Sie C-Style Casting in C++.

+0

Hat nicht funktioniert. Immer noch der gleiche Fehler. – tik