0

Based on this answer about encoding/decoding to base 64, and this answer about converting from float to byte vector and back, I was trying to convert a float vector to a hex or binary string.

This is my code:

vector<float> floats = ...;
const unsigned char* bytes = reinterpret_cast<const unsigned char*>(&floats[0]);
std::vector<unsigned char> byteVec(bytes, bytes + sizeof(float) * floats.size());
std::cout<<byteVec.size()<<std::endl;
std::string dat = base64_encode(&byteVec[0], byteVec.size());
std::vector<unsigned char> decodedData = base64_decode(dat);
std::cout<<decodedData.size()<<std::endl;
unsigned char* bytesN = &(decodedData[0]);    // point to beginning of memory
float* floatArray = reinterpret_cast<float*>(bytesN);
std::vector<float> floatVec(floatArray, floatArray + sizeof(unsigned char) * decodedData.size());   
std::cout<<floatVec.size()<<std::endl;

The original vector, floats, is 262,144 floats, and both cout statements print 1048576, and then the program segfaults. What am I doing wrong?

Also, is there a better or faster method to accomplish this? I want to send the string using xml/gsoap, so if gsoap has a function to do this automatically, it would make my life a lot easier.

anc
  • 191
  • 1
  • 19
  • `unsigned char* bytesN = &(decodedData[0]); float* floatArray = reinterpret_cast(bytesN);` - It is undefined to reinterpret a block of `char`s as another type. It violates aliasing rules. Only the converse is allowed. You should `memcpy` the bytes into an actual, declared & allocated, array of `floats` & then read that. Even that is brittle as you are making assumptions about how the implementation represents `float` & whether that matches the one that encoded them. Also, there could be other problems; it's hard to read this solid lump of code. Some newlines and comments would be nice. – underscore_d Aug 03 '17 at 13:03
  • 1
    So you have one vector of `float` elements. For every element you want to hex-encode it into a string in a new vector? And then decode the new vector into a second vector of `float`? That's as simple as two calls to [`std::transform`](http://en.cppreference.com/w/cpp/algorithm/transform). – Some programmer dude Aug 03 '17 at 13:04
  • @Someprogrammerdude well, I want the whole vector to be one hex string, not a new vector of other strings. Would transform still work for that? – anc Aug 03 '17 at 13:05
  • Or do you want to create a single hex-encoded string of *all* elements in the vector, and then convert them back into a second vector? – Some programmer dude Aug 03 '17 at 13:05
  • @Someprogrammerdude yup, the latter! – anc Aug 03 '17 at 13:05

1 Answers1

1

One major problem is this:

std::vector<float> floatVec(floatArray, floatArray + sizeof(unsigned char) * decodedData.size());

Here you say that the number of elements would be decodedData.size(), which is 1048576. But it's wrong since it should only be a quarter of that (because decodedData.size() is the size in bytes not in the number of float elements). This will of course lead to going out of bounds of decodedData which leads to undefined behavior.

You need to divide the size of decodedData.size() with sizeof(float):

std::vector<float> floatVec(floatArray, floatArray + decodedData.size() / sizeof(float));
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621