I really can't explain this behaviour

I've made a simple byte array buffer that serializes and deserializes floating point numbers by casting them to unsigned char*

From my tests I can see that I can serialize everything correctly into the buffer.
But when I try to deserialize the values back into float and double variables I only get one or two variables populated, the rest are zeros.

If someone if willing to compile and run the code to see if all the results get populated and to tell me if I've mistaken anywhere, that would be nice.

The test [main.cpp] http://pastebin.com/hz1E5MHP
The header [buffer.h] http://pastebin.com/wfQnJycF
The code [buffer.cpp] http://pastebin.com/4HFCi464
What do you mean? Can you give us an example?
It looks to me as if you have your indexes reversed in the "read" functions, leading to undefined behavior. bytes should not be indexed with read, and you only ever access the first 4/8 bytes of the buffer in the "read" functions.
In main.h you can see that I do
1
2
3
4
    buffer.tryWriteFloat(f1);
    buffer.tryWriteFloat(f2);
    buffer.tryWriteDouble(d1);
    buffer.tryWriteDouble(d2);

and after that
1
2
3
4
    buffer.tryReadFloat(_f1);
    buffer.tryReadFloat(_f2);
    buffer.tryReadDouble(_d1);
    buffer.tryReadDouble(_d2);

But at the end not all of the variables get copied or not correctly. Only the first one does. Doesn't matter if the first one is float or double.

The function names have "try" in them because it will return false if the end of the buffer is reached.
Those functions access the buffer sequentially. And Read & Write are independent (although you have to write before reading).

Btw i've made a version for integers first, which worked great, but the problem begun when I wanted to support floating point numbers
Last edited on
cire, How are indices reversed? I don't understand.

And I do increment `read' at the end of the functions.
For example, you write :
Float
125.50
175.50

Double
225.50
265.25

And you read the buffer to represent the exact these values?
From what I see, buffer can normally hold a value at one time. So please do it like this :
1
2
3
4
5
6
7
8
9
10
11
buffer.tryWriteFloat(f1);
buffer.tryReadFloat(_f1);

buffer.tryWriteFloat(f2);
buffer.tryReadFloat(_f2);

buffer.tryWriteDouble(d1);
buffer.tryReadDouble(_d1);

buffer.tryWriteDouble(d2);
buffer.tryReadDouble(_d2);
SakurasouBusters, The thing with this buffer I made is that you can use it as a file.
First write all your data, then read all of it.
In my example it allocates 1000 bytes on the heap.
Ofc you can use this to store a value at a time, but that was not my intent.

Anyway I solved my problem by doing
1
2
3
4
5
6
7
8
bool Buffer::tryWriteFloat(float val)
{
    return tryWriteUInt(*(unsigned long*)&val);
}
bool Buffer::tryReadFloat(float& val)
{
    return tryReadUInt(*(unsigned long*)&val);
}

Where those functions are defined as
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool Buffer::tryWriteUInt(unsigned long val)
{
	if(RemainingSpace() < 4) return false;
	buffer[written    ] = (val & 0xff000000) >> 24;
	buffer[written + 1] = (val & 0x00ff0000) >> 16;
	buffer[written + 2] = (val & 0x0000ff00) >> 8;
	buffer[written + 3] = (val & 0x000000ff);
	written += 4;
	return true;
}
bool Buffer::tryReadUInt(unsigned long& val)
{
	if(RemainingData() < 4) return false;
	val = 0;
	val |= ((unsigned long)buffer[read    ]) << 24;
	val |= ((unsigned long)buffer[read + 1]) << 16;
	val |= ((unsigned long)buffer[read + 2]) << 8;
	val |= ((unsigned long)buffer[read + 3]);
	read += 4;
	return true;
}

And I did the same with double and unsigned long long.

From some reason the compilers really don't like it when you use float/double as a char[]. And using optimizations -o2 or -o3 even causes errors.

The problem I was looking to solve with this buffer is that I had a lot of numbers to send over a socket and I didn't want to use the send function every time.

At the moment I am doing send(mSocket, (char*)&theNumber, 8, 0); which works great, but I end up with a ton of calls to send function for literally few bytes at a time.
cire, How are indices reversed? I don't understand.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool Buffer::tryReadFloat(float& val)
{
    if(RemainingData() < 4) return false;
    register unsigned char* bytes = (unsigned char*)&val;
    bytes[read    ] = buffer[3];
    bytes[read + 1] = buffer[2];
    bytes[read + 2] = buffer[1];
    bytes[read + 3] = buffer[0];
    bytes[3] = buffer[read];
    bytes[2] = buffer[read + 1];
    bytes[1] = buffer[read + 2];
    bytes[0] = buffer[read + 3];

    read += 4;
    return true;
}


Likewise with the read for double. I haven't bothered verifying other parts of the code, but that jumped out at me.
Ahhh now I understand.

I must have made the mistake when I copied the code from Write to Read function and didn't switch the indices.

I was looking at the code for hours without seeing the mistake.

Thanks cire!
Topic archived. No new replies allowed.