динамически создать вектор внутри конструктора класса B, когда класс A выделяет память при построении - PullRequest
1 голос
/ 05 мая 2020

Я встроенный разработчик. И теперь я являюсь частью проекта, который использует c ++, поскольку наш µ C не поддерживал c ++, мой c ++ стал немного ржавым. Я надеюсь, что некоторые из вас могут мне помочь.

Я хочу смоделировать соединение шины SPI с динамической c длиной данных и количеством подчиненных устройств. Поскольку этот код проверяет некоторый код µ C, написанный простым старым C, необходимо, чтобы интерфейс симуляции работал с массивами, а не с контейнерами.

Вот объявленные мною классы, описание следующая моя проблема.

class LSPI_BusSymulation_SlaveDevice;

class LSPI_BusSymulation{ //Interface to the Symulation-Klass
public:
    LSPI_BusSymulation(uint16_t dataSizePerDevice, uint16_t maxNumberOfDevices, uint16_t actualNumberOfDevices);

    // must use normal arrays
    uint16_t* sendSpiData(uint16_t* data, uint16_t dataSize);
private:
    uint16_t actualNumberOfDevices;
    std::vector<LSPI_BusSymulation_SlaveDevice> devices;
};

class LSPI_BusSymulation_SlaveDevice{//Symulates one bus-device, there can be several
    friend LSPI_BusSymulation;
public:
    LSPI_BusSymulation_SlaveDevice(uint16_t dataSizePerDevice, uint16_t maxNumberOfDevices);
    ~LSPI_BusSymulation_SlaveDevice();

    // must use normal arrays
    void prepareResponse(uint16_t* data, uint16_t dataSize);
    uint16_t* getBusData();

private:
    // must use normal arrays
    uint16_t* putData(uint16_t* data, uint16_t dataSize);

    uint16_t dataSizePerDevice;
    uint8_t* data;
};

Класс LSPI_BusSymulation должен создать вектор с actualNumberOfDevices * LSPI_BusSymulation_SlaveDevice внутри его конструктора. Как правильно реализовать конструктор LSPI_BusSymulation, не создавая утечек памяти? Вот что у меня есть на данный момент. (Другие методы пока не важны)

LSPI_BusSymulation_SlaveDevice::LSPI_BusSymulation_SlaveDevice(uint16_t dataSizePerDevice, uint16_t maxNumberOfDevices)
    : dataSizePerDevice(dataSizePerDevice){
    data = new uint8_t[dataSizePerDevice * (maxNumberOfDevices + 1)];
}

LSPI_BusSymulation_SlaveDevice::~LSPI_BusSymulation_SlaveDevice(){
    delete data;
}

void LSPI_BusSymulation_SlaveDevice::prepareResponse(uint16_t* data, uint16_t dataSize){
    memcpy(this->data, data, dataSize);
}

uint16_t* LSPI_BusSymulation_SlaveDevice::getBusData(){
    return (uint16_t*)this->data;
}

uint16_t* LSPI_BusSymulation_SlaveDevice::putData(uint16_t* data, uint16_t dataSize){
    memcpy(&this->data[this->dataSizePerDevice], data, dataSize);

    return (uint16_t*)this->data;
}

LSPI_BusSymulation::LSPI_BusSymulation(uint16_t dataSizePerDevice, uint16_t maxNumberOfDevices, uint16_t actualNumberOfDevices)
    : actualNumberOfDevices(actualNumberOfDevices){
    //create a vector with actualNumberOfDevices * LSPI_BusSymulation_SlaveDevice
    //Does that work, or will I lose the array inside the created class?
    for(int i = 0; i < actualNumberOfDevices; i++)
        devices.push_back(LSPI_BusSymulation_SlaveDevice(dataSizePerDevice, maxNumberOfDevices));
}

uint16_t* LSPI_BusSymulation::sendSpiData(uint16_t* data, uint16_t dataSize){
    uint16_t* retPtr = data;

    for(int i = 0; i < this->actualNumberOfDevices; i++)
        retPtr = devices[i].putData(retPtr, dataSize);

    return retPtr;
}

Я видел много сообщений об этой проблеме, но ни в одном из этих сообщений не было класса с динамической c выделенной памятью внутри него. И я не уверен, что это проблема.

Если я запустил этот простой main:

int main(){    
    LSPI_BusSymulation test(10, 10, 10);

   return 0;
}

, я получаю следующую ошибку: * Ошибка в `./a .out ': двойное освобождение или повреждение (fasttop): 0x0000000000ea0c20 *

Надеюсь, я предоставил всю информацию.

1 Ответ

2 голосов
/ 05 мая 2020

Если вы используете C ++, используйте стандартные контейнеры таким образом, вам не придется беспокоиться об освобождении памяти. Вы всегда можете получить доступ к данным, выделенным контейнером, если хотите получить указатель на необработанный массив.

Некоторая модификация вашего кода

class LSPI_BusSymulation{
...
private:
    // must use normal arrays
    uint16_t* putData(uint16_t* data, uint16_t dataSize);

    uint16_t dataSizePerDevice;
     std::vector<uint8_t> data;
};

конструктор:

LSPI_BusSymulation_SlaveDevice::LSPI_BusSymulation_SlaveDevice(uint16_t dataSizePerDevice, uint16_t maxNumberOfDevices)
    : dataSizePerDevice(dataSizePerDevice){
    data.resize(dataSizePerDevice * (maxNumberOfDevices + 1));
}

Доступ к данным (пример кода)

uint16_t* LSPI_BusSymulation_SlaveDevice::getBusData(){
    return (uint16_t*)this->data.data(); // access to the container underlying allocated raw data
}
...