gfree
gfree

Reputation: 507

std::copy resulting in "Stack around the variable " was corrupted" error

I am currently trying to copy 4 bytes out of a vector<BYTE> into an integer value. When my function returns, I continually get an error that my stack is corrupted (Stack around the variable 'rxPacket' was corrupted). I am running in debug mode and debugging my DLL. I stripped the function down to something very basic shown below, but I still get the resulting error. I did find this issue and I'm wondering if I am experiencing something similar. But, I wanted to check to see if there was something obvious I am missing.

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

Upvotes: 0

Views: 105

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 597166

rxCommandStringLength is an int, so &rxCommandStringLength is an int*. Let's just assume for the sake of argument that sizeof(int) is 4 bytes 1.

1: to really ensure that exactly 4 bytes are being copied, you should be using int32_t instead of int, since int is not guaranteed to be 4 bytes on all platforms.

Iterators (which includes raw pointers) are incremented/decremented in terms of whole elements, not bytes. The element type is whatever type is returned when the iterator is dereferenced.

Since your input iterator is a vector::iterator to a BYTE array, and your output iterator is an int* pointer, reverse_copy() will iterate through the source array in whole BYTEs and through the destination memory in whole ints, not in single bytes like you are expecting. In other words, when reverse_copy() increments the input iterator it will jump forward by 1 byte, but when it increments the destination iterator it will jump forward in memory by 4 bytes.

In this example, reverse_copy() will read the 1st input BYTE and write the value to the 1st output int, then read the 2nd input BYTE and write the value to the 2nd output int, and so on, and so on. By the end, the input iterator will have advanced by 4 BYTEs, and the destination pointer will have advanced by 4 ints - 16 bytes total, which goes WAY beyond the bounds of the actual rxCommandStringLength variable, and thus reverse_copy() will have written into surrounding memory, corrupting the stack (if it doesn't just crash instead).

Since you want reverse_copy() to iterate in 1-byte increments for BOTH input AND output, you need to type-cast the int* pointer to match the data type used by the input iterators, eg:

std::reverse_copy(readBuffer.begin(), readBuffer.begin() + sizeof rxCommandStringLength, reinterpret_cast<BYTE*>(&rxCommandStringLength));

Upvotes: 3

Related Questions