运行GTest时指针无效

时间:2016-05-03 11:45:08

标签: c++ googletest

问题是:

  <。>`。/ runTests'出错:free():无效指针:0x00007fdb92fe27a0已中止

测试套件是:

#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();
}

函数checksum是:

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

编辑*:添加了serial::BufferWrapper

#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 *添加了声明:

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

运行测试的完整打印输出是:

[==========] 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

为什么在测试运行并完成并且测试套件中的指针被创建和销毁时会发生这种情况?

1 个答案:

答案 0 :(得分:1)

我敢打赌问题是这个初始化:

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

这里你分配了一个serial::BufferWrapper对象,但是你将指针转换为std::unique_ptr<...> 对象,这意味着编译器会调用std::unique_ptr<...> 运动 constructor。应该调用的构造函数应该是指向包装类型的指针。

因此,要解决问题,请跳过转换并执行

bw(new serial::BufferWrapper)

这里有什么教训?永远永远在C ++中使用C风格的转换。