I am wondering why the pointer value (324502) is in var signalLengthDebugVar1 instead of the expected integer value (2)?
struct ShmLengthOfSignalName {
int signalLength;
};
//...
BYTE* pBuf = NULL;
//...
int main(void){
//...
pBuf = (BYTE*) MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);
//...
JobaSignal sig1;
printf("Value SignalLength: %d \r\n", pBuf[30]); // 2
const ShmLengthOfSignalName * signalNameLengthPtr = (const ShmLengthOfSignalName *)(pBuf + 30);
int signalLengthDebugVar1 = signalNameLengthPtr->signalLength; // content: 324502 maybe pointer?
int signalLengthDebugVar2 = (int) pBuf[30]; // content 2
sig1.setNameLength(signalLengthDebugVar2);
}
When you print the value, you're reading only the single byte at pBuf + 30:
// takes pBuf[30], converts that byte's value to int, and prints it
printf("Value SignalLength: %d \r\n", pBuf[30]); // 2
Later, when you cast the pointer and dereference it, you're accessing a full int, which is sizeof(int) bytes (likely 4). This occupies not just the byte at pBuf + 30 but also the subsequent bytes at pBuf + 31, etc., up to sizeof(int) on your platform. It also interprets these bytes according to your platform's byte-endianness (little-endian for Intel, big-endian for most other platforms).
// the signalLength struct member is an int
int signalLengthDebugVar1 = signalNameLengthPtr->signalLength; // content: 324502 maybe pointer?
Note also that the compiler is permitted to add padding before or after the loation of its signalLength field. In other words, you can't assume that signalLength will start at struct offset zero, unless you use extern "C" or a compiler-specific #pragma. And even then, you can't control the endianness interpretation, so if the data was encoded as big-endian and you're on a little-endian machine like x86, the value you see will be wrong.
The bottom line is that in C++ this is not a safe way to decode binary data.
Related
I am having issues assigning value to unsigned short* and unsigned char* buffers. The code looks something like this:
// Header File
unsigned short* short_buff;
unsigned char* char_buff;
// Implementation File
short_buff = new unsigned short[10];
memset(&short_buff, 0, 10);
char_buff = new unsigned char[10];
memset(&char_buff, 0, 10);
unsigned short sVal = 0;
unsigned char cVal = 0x0;
// All of these cause core dumps
short_buff[0] = sVal;
memcpy(&short_buff[0], &sVal, 2); // 2 bytes per unsigned short
std::cout << short_buff[0] << std::endl;
// All of these also cause core dumps
char_buff[0] = cVal;
memcpy(&char_buff[0], &cVal, 1); // 1 byte per unsigned char
std::cout << char_buff[0] << std::endl;
// Yet strangely these cause no issues
unsigned short s2Val = short_buff[0];
unsigned char c2Val = char_buff[0];
I am completely at a loss as to what is going on here and why.. Any help would be greatly appreciated!
memset(short_buff, 0, 10*sizeof(short));
and
memset(char_buff, 0, 10*sizeof(char));
Two mistakes, & is wrong, you should pass the value of the pointer to memset not the address of the pointer variable. (This version memset(&short_buffer[0], ...); also works).
Secondly memset counts bytes not elements, so you need to multiply the array size by the element size, use sizeof for that.
Strangely you got it more or less right with memcpy later on. Why not the same thing for memset?
Consider the following c++ code:
unsigned char* data = readData(..); //Let say data consist of 12 characters
unsigned int dataSize = getDataSize(...); //the size in byte of the data is also known (let say 12 bytes)
struct Position
{
float pos_x; //remember that float is 4 bytes
double pos_y; //remember that double is 8 bytes
}
Now I want to fill a Position variable/instance with data.
Position pos;
pos.pos_x = ? //data[0:4[ The first 4 bytes of data should be set to pos_x, since pos_x is of type float which is 4 bytes
pos.pos_x = ? //data[4:12[ The remaining 8 bytes of data should be set to pos_y which is of type double (8 bytes)
I know that in data, the first bytes correspond to pos_x and the rest to pos_y. That means the 4 first byte/character of data should be used to fill pos_x and the 8 remaining byte fill pos_y but I don't know how to do that.
Any idea? Thanks. Ps: I'm limited to c++11
You can use plain memcpy as another answer advises. I suggest packing memcpy into a function that also does error checking for you for most convenient and type-safe usage.
Example:
#include <cstring>
#include <stdexcept>
#include <type_traits>
struct ByteStreamReader {
unsigned char const* begin;
unsigned char const* const end;
template<class T>
operator T() {
static_assert(std::is_trivially_copyable<T>::value,
"The type you are using cannot be safely copied from bytes.");
if(end - begin < static_cast<decltype(end - begin)>(sizeof(T)))
throw std::runtime_error("ByteStreamReader");
T t;
std::memcpy(&t, begin, sizeof t);
begin += sizeof t;
return t;
}
};
struct Position {
float pos_x;
double pos_y;
};
int main() {
unsigned char data[12] = {};
unsigned dataSize = sizeof data;
ByteStreamReader reader{data, data + dataSize};
Position p;
p.pos_x = reader;
p.pos_y = reader;
}
One thing that you can do is to copy the data byte-by byte. There is a standard function to do that: std::memcpy. Example usage:
assert(sizeof pos.pos_x == 4);
std::memcpy(&pos.pos_x, data, 4);
assert(sizeof pos.pos_y == 8);
std::memcpy(&pos.pos_y, data + 4, 8);
Note that simply copying the data only works if the data is in the same representation as the CPU uses. Understand that different processors use different representations. Therefore, if your readData receives the data over the network for example, a simple copy is not a good idea. The least that you would have to do in such case is to possibly convert the endianness of the data to the native endianness (probably from big endian, which is conventionally used as the network endianness). Converting from one floating point representation to another is much trickier, but luckily IEE-754 is fairly ubiquitous.
Whenever I load a struct into memory the memory block seems to contain ffffff before certain bytes. After closer inspection I figured this occurs exactly at 0x80 (128 in dec).
#include <Windows.h>
#include <stdio.h>
typedef struct __tagMYSTRUCT {
BYTE unused[4096];
} MYSTRUCT, *PMYSTRUCT;
int main() {
MYSTRUCT myStruct;
for (int i = 0; i < 4094; i++) {
myStruct.unused[i] = 0x00;
}
myStruct.unused[4094] = 0x7F; /* No FFFFFF prepend */
myStruct.unused[4095] = 0x80; /* FFFFFF prepend */
MYSTRUCT *p = (MYSTRUCT*)malloc(4096);
*p = myStruct;
char *read = (char*)p;
for (int i = 0; i < 4096; i++) {
printf("%02x ", read[i]);
}
free(p);
p = NULL;
read = NULL;
return 0;
}
Any one knows why this happens and / or how to 'fix' it? (I assume bytes should reach to 0xff); if I write these bytes to a file, as in, fwrite(&myStruct, sizeof(myStruct), 1, [filestream]) it doesn't include the ffffff's
Compiler used: Visual Studio 2015 Community
P.S. as stated in the title the same occurs when using VirtualAlloc
This has nothing to do with VirtualAlloc nor with malloc.
Note that the following details depend on your platform and different things might happen on different operating systems or compilers:
char is a signed type (on your platform). It has a range of -128 to 127. When you treat the number 128 as a char it wraps around and is actually stored as -128.
%02x tells printf to print an unsigned int, in hexadecimal, with at least two digits. But you are actually passing a char. The compiler will automatically convert it to an int (with the value -128), which printf will then misinterpret as an unsigned int. On your platform, -128 converted to an unsigned int will give the same value as 0xffffff80.
I have a char buffer buf containing buf[0] = 10, buf[1] = 3, buf[2] = 3, buf[3] = 0, buf[4] = 58,
and a structure:
typedef struct
{
char type;
int version;
int length;
}Header;
I wanted to convert the buf into a Header. Now I am using the function
int getByte( unsigned char* buf)
{
int number = buf[0];
return number;
}
int getInt(unsigned char* buf)
{
int number = (buf[0]<<8)+buf[1];
return number;
}
main()
{
Header *head = new Header;
int location = 0;
head->type = getByte(&buf[location]);
location++; // location = 1
head->version = getInt(&buf[location]);
location += 2; // location = 3
head->ength = getInt(&buf[location]);
location += 2; // location = 5
}
I am searching for a solution such as
Header *head = new Header;
memcpy(head, buf, sizeof(head));
In this, first value in the Header, head->type is proper and rest is garbage. Is it possible to convert unsigned char* buf to Header?
The only full portable and secure way is:
void convertToHeader(unsigned char const * const buffer, Header *header)
{
header->type = buffer[0];
header->version = (buffer[1] << 8) | buffer[2];
header->length = (buffer[3] << 8) | buffer[4];
}
and
void convertFromHeader(Header const * const header, unsigned char * buffer)
{
buffer[0] = header->type;
buffer[1] = (static_cast<unsigned int>(header->version) >> 8) & 0xFF;
buffer[2] = header->version & 0xFF;
buffer[3] = (static_cast<unsigned int>(header->length) >> 8) & 0xFF;
buffer[4] = header->length & 0xFF;
}
Example
see Converting bytes array to integer for explanations
EDIT
A quick summary of previous link: other possible solutions (memcpy or union for example) are no portable according endianess of different system (doing what you do is probably for a sort of communication between at least two heterogeneous systems) => some of systems byte[0] is LSB of int and byte[1] is MSB and on other is the inverse.
Also, due to alignement, struct Header can be bigger than 5 bytes (probably 6 bytes in your case, if alignement is 2 bytes!) (see here for example)
Finally, according alignment restrictions and aliasing rules on some platform, compiler can generate incorrect code.
What you want would need your version and length to have the same length as 2 elements of your buf array; that is you'd need to use the type uint16_t, defined in <cstdint>, rather than int which is likely longer. And also you'd need to make buf an array of uint8_t, as char is allowed to take more than 1 byte!
You probably also need to move type to the end; as otherwise the compiler will almost certainly insert a padding byte after it to be able to align version to a 2-byte boundary (once you have made it uint16_t and thus 2 bytes); and then your buf[1] would end up there rather than were you want it.
This is probably what you observe right now, by the way: by having a char followed by an int, which is probably 4 bytes, you have 3 bytes of padding, and the elements 1 to 3 of your array are being inserted there (=lost forever).
Another solution would be to modify your buf array to be longer and have empty padding bytes as well, so that the data will be actually aligned with the struct fields.
Worth mentioning again is that, as pointed out in the comments, sizeof(head) returns the size of pointers on your system, not of the Header structure. You can directly write sizeof(Header); but at this level of micromanagement, you wont be losing any more flexibility if you just write "5", really.
Also, endianness can screw with you. Processors have no obbligation to store the bytes of a number in the order you expect rather than the opposite one; both make internal sense after all. This means that blindly copying bytes buf[0], buf[1] into a number can result in (buf[0]<<8)+buf[1], but also in (buf[1]<<8)+buf[0], or even in (buf[1]<<24)+(buf[0]<<16) if the data type is 4 bytes (as int usually is). And even if it works on your computer now, there is at least one out there where the same code will result in garbage. Unless, that is, those bytes actually come from reinterpreting a number in the first place. In which case the code is wrong (not portable) now, however.
...is it worth it?
All things considered, my advice is strongly to keep the way you handle them now. Maybe simplify it.
It really makes no sense to convert a byte to an int then to byte again, or to take the address of a byte to dereference it again, nor there is need of helper variables with no descriptive name and no purpose other than being returned, or of a variable whose value you know in advance at all time.
Just do
int getTwoBytes(unsigned char* buf)
{
return (buf[0]<<8)+buf[1];
}
main()
{
Header *head = new Header;
head->type = buf[0];
head->version = getTwoBytes(buf + 1);
head->length = getTwoBytes(buf + 3);
}
the better way is to create some sort of serialization/deserialization routines.
also, I'd use not just int or char types, but would use more specific int32_t etc. it's just platform-independent way (well, actually you can also pack your data structures with pragma pack).
struct Header
{
char16_t type;
int32_t version;
int32_t length;
};
struct Tools
{
std::shared_ptr<Header> deserializeHeader(const std::vector<unsigned char> &loadedBuffer)
{
std::shared_ptr<Header> header(new Header);
memcpy(&(*header), &loadedBuffer[0], sizeof(Header));
return header;
}
std::vector<unsigned char> serializeHeader(const Header &header)
{
std::vector<unsigned char> buffer;
buffer.resize(sizeof(Header));
memcpy(&buffer[0], &header, sizeof(Header));
return buffer;
}
}
tools;
Header header = {'B', 5834, 4665};
auto v1 = tools.serializeHeader(header);
auto v2 = tools.deserializeHeader(v1);
I have problems to access and modify my multiple thread data. Is there are any proper way to do this?
Here is my full code:
#include <stdio.h>
#include <windows.h>
// Create thread data structure
struct data
{
int a;
float b;
char *c;
};
DWORD WINAPI threadfn(LPVOID lpParam)
{
printf("Address of thread data:\n");
for(int i=0; i<sizeof(lpParam); i++)
printf("%X\n", (int*)lpParam + i);
// Print out initial values
printf("\nInitial values:\n");
printf("a: %d\n", *((int*)lpParam));
printf("b: %.2f\n", *((float*)lpParam + 1));
printf("c: %s\n", *((int*)lpParam + 2));
// Modify thread data values
*(int*)lpParam = 200;
*((float*)lpParam + 1) = 25.80;
*((char*)lpParam + 2) = "Es la una";
return 0;
}
int main()
{
HANDLE hThread;
data thread;
// Set initial thread data values
thread.a = 10; // Integer data type
thread.b = 15.60; // Float data type
thread.c = "Que hora es?"; // String data type
hThread = CreateThread(NULL, 0, threadfn, &thread, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
// Print out thread value after modification
printf("\nAfter thread modifications:\n");
printf("a: %d\n", thread.a);
printf("b: %.2f\n", thread.b);
printf("c: %s\n", thread.c);
getchar();
return 0;
}
And this is my output:
Address of thread data:
28FF20
28FF24
28FF28
28FF2C
Initial values:
a: 10
b: 15.60
c: Que hora es?
After thread modifications:
a: 7405768
b: 25.80
c: Que hora es?
As you can see, the 'c' value is same. How do i modify string value?
What on earth are you doing?! All the casting of lpData is very, very wrong. If you have to do that much casting to accomplish something, you are probably not doing it the right way.
Anyway, your code should look like this:
DWORD WINAPI threadfn(LPVOID lpParam)
{
printf("Address of thread data:\n");
data *lpData = (data *)(lpParam);
for(int i=0; i<sizeof(lpParam); i++)
printf("%X\n", (int*)lpParam + i);
// Print out initial values
printf("\nInitial values:\n");
printf("a: %d\n", lpData->a);
printf("b: %.2f\n", lpData->b);
printf("c: %s\n", lpData->c);
// Modify thread data values
lpData->a = 200;
lpData->b = 25.80;
lpData->c = "Es la una";
return 0;
}
You should be using (data *)(lpParam) because it basically reverses what's happening when you call CreateThread. Personally, think the stupid P notation for type names is more of a hinderance than a help because it obscures what's actually happening. Hungarian notation in general has this problem IMHO.
In your main function, you have this code:
hThread = CreateThread(NULL, 0, threadfn, &thread, 0, NULL);
The 4th argument to CreateThread is a void * (aka a PVOID). The type of the expression &thread is data *. This means that the data * is being implicitly converted to a void *. If you make that conversion explicit, the code looks like this:
hThread = CreateThread(NULL, 0, threadfn, (void *)(&thread), 0, NULL);
So, in order to 'undo' what was done, you need to 'reverse' the cast. You need to turn the void * back into a data *, which means than in threadfn you need the code data *lpData = (data *)(lpParam);.
Additionally, you are courting disaster by setting c to point at constant character strings since you didn't declare it as a const char *. I'm surprised the compiler isn't giving you an error. The disaster happens when you do something like data.c[0] = 'f';. When you do that you will be trying to modify memory that may very well be flagged as read-only and cause your program to crash. And that's the kindest thing that could happen.
You're not accessing your structure members properly from within the spawned thread. Consider this:
*(int*)lpParam = 200;
It means convert the lpParam to an int*, then access the integer at that address. That works fine, but:
*((float*)lpParam + 1) = 25.80;
Converts lpParam to a float*, then adds sizeof(float*) bytes to it, then dereferences it. That only works if sizeof(int) happens to be the same as sizeof(float)... which is common enough but not guaranteed.
*((char*)lpParam + 2) = "Es la una";
This is a real worry though: this considers lpParam a char*, then adds two BYTES to it, which probably positions it half way into the four bytes used by the integer member of the struct (assuming a 32 bit app), then writes over the single character at that address with a truncated value (the least significant byte/char) from the char pointer to your new string [incorporating correction thanks to Chris's comment].
Instead:
data* p = (data*)lpParam;
p->a = ...;
p->b = ...;
p->c = ...;
The basic point here is that the thread function takes a void* argument, so you lose the type information. The first thing you want to do with it when your thread starts running is restore that type information so the compiler can check what you're doing is safe and sensible.
Your pointer arithmetic is off.
c is at offset 8 in the struct.
However:
*((char*)lpParam + 2) = "Es la una";
You cast lpParam to a char*. Char's have a size of 1 byte (on Windows at least.) You add two to the pointer, so you are writing to offset 2 bytes in the struct.
Your other pointer arithmetic happens to work since you cast lpParam to a float*, meaning (float*)lpParam + 1 writes to offset 4 in the struct.
As Omnifarius suggested, just cast lpParam to a pointer to the thread data structure and access the members through that.