Inside a test, I write a given value to an ostringstream. After that, I try to evaluate if the correct value was written. However, it seems that the original value I wrote into the stream is changed later on while reading from it.
I reduced my problem to the following code:
#include <sstream>
#include <cassert>
#include <iostream>
int main()
{
std::ostringstream os;
uint16_t data{ 123 };
os.write(reinterpret_cast<const char*>(&data), sizeof(uint16_t));
uint16_t data_returned;
std::string data_str(os.str());
std::copy(data_str.begin(), data_str.end(), &data_returned);
assert(data == 123); // <- not true
assert(data_returned == 123);
}
Here data seems to be changed (to 0) by std::copy().
I also put the code on godbolt: https://godbolt.org/z/bcb4PE
Even more strange, if I change uint16_t data{ 123 }; to const uint16_t data{ 123 };, everything is fine.
Seems like I am missing some insights on the mechanics of std::copy().
std::copy()does not do what you think it does in this situation. It is just a wrapper for a logical loop that copies individual elements from one container to another. You are essentially telling it to copy 2 individualcharsfromdata_strinto auint16_t[2]array, except that you don't actually have such as array, so you have undefined behavior and are corrupting stack memory.This statement:
Is basically doing this:
Which is basically just the equivalent of doing this, in your example:
It is assigning the 1st byte to the whole
uint16_t(which is why you see the value change), and then it is assigning the 2nd byte to the next wholeuint16_t(corrupting the stack).For what you are attempting, use
std::memcpy()instead, eg:Otherwise, if you really want to use
std::copy(), you need to make sure it knows to copy individual bytes into the destination, not wholeuint16_ts, eg:Since both input and output are trivial types, that should get optimized down to an appropriate
std::memcpy()-equivalent copy.