std :: copy, приводящий к ошибке "Stack вокруг переменной" был поврежден " - PullRequest
0 голосов
/ 10 апреля 2020

Я сейчас пытаюсь скопировать 4 байта из vector<BYTE> в целочисленное значение. Когда моя функция возвращается, я постоянно получаю сообщение об ошибке, что мой стек поврежден (стек вокруг переменной 'rxPacket' был поврежден). Я работаю в режиме отладки и отладки моей DLL. Я сократил функцию до чего-то очень базового c, показанного ниже, но я все еще получаю полученную ошибку. Я нашел эту проблему , и мне интересно, испытываю ли я что-то подобное. Но я хотел проверить, было ли что-то очевидное, чего мне не хватает.

AtpSocket::RxPacket AtpSocket::sendAndWait(AtpSocket::Command cmd,const void* data,size_t dataLen,int timeout) {
    AtpSocket::TxPacket txPacket;
    AtpSocket::RxPacket rxPacket;

    int rxCommandStringLength = 0;
    std::vector<BYTE> readBuffer(20, 55);
    std::reverse_copy(readBuffer.begin(), readBuffer.begin() + sizeof rxCommandStringLength, &rxCommandStringLength);

    return rxPacket;
}

1 Ответ

3 голосов
/ 10 апреля 2020

rxCommandStringLength - это int, поэтому &rxCommandStringLength - это int*. Давайте просто предположим ради аргумента, что sizeof(int) - это 4 байта 1 .

1: чтобы действительно гарантировать, что копируется ровно 4 байта, вы должны использовать int32_t вместо int, поскольку int не гарантируется равным 4 байтам на всех платформах.

Итераторы (включая необработанные указатели) увеличиваются / уменьшаются в единицах целых элементов, а не байт. Тип элемента - это любой тип, возвращаемый при разыменовании итератора.

Поскольку входной итератор представляет собой массив vector::iterator to BYTE, а выходной итератор - указатель int*, reverse_copy() будет перебирать исходный массив в целом BYTE с и через целевую память в целом int с, а не в отдельных байтах, как вы ожидаете. Другими словами, когда reverse_copy() увеличивает входной итератор, он переходит вперед на 1 байт, но когда он увеличивает целевой итератор, он переходит вперед в памяти на 4 байта.

В этом примере reverse_copy() будет читать 1-й вход BYTE и записывать значение в 1-й выход int, затем читать 2-й вход BYTE и записывать значение во 2-й выход int, и так далее, и так далее. К концу входной итератор будет продвинут на 4 BYTE с, а указатель назначения будет продвинут на 4 int с - всего 16 байт, что выходит за пределы действительной переменной rxCommandStringLength, и таким образом, reverse_copy() будет записано в окружающую память, повреждая стек (если он не просто взломает sh).

Так как вы хотите, чтобы reverse_copy() итерировал с шагом в 1 байт для ОБА ввода И вывод, вам нужно привести указатель int*, чтобы он соответствовал типу данных, используемому итераторами ввода, например:

std::reverse_copy(readBuffer.begin(), readBuffer.begin() + sizeof rxCommandStringLength, reinterpret_cast<BYTE*>(&rxCommandStringLength));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...