Jochen
Jochen

Reputation: 1776

C++ move bytewise through memory

I have a shared memory with this structure (see codesnippet 1), all values are hex values:

Position 00:  55; // memory overall, byte 00 to 03;
Position 01:  00;
Position 02:  00;
Position 03:  00;
Position 04:  47; // memory for header information, byte 04 to 07;
Position 05:  00
Position 06:  00;
Position 07:  00;
Position 08:  00; // version, byte 08, 09;
Position 09:  00;
Position 0A:  64; // rate of refreshing memory between processes
Position 0B:  00;
Position 0C:  00;
Position 0D:  00;
Position 0E:  00;
Position 0F:  4L;
...

As you can see in the comments I know which byte represents what information. Anyway I cast the memory in a struct (see codesnippet 2). The properties in this struct are currently integer-values. The values 55 and 47 are stored in the first two properties. As it seems, '00' will be neglected and I am not able to read the whole memory byte by byte. How can I read the memory bytewise?

codesnippet 2:

struct Shm {
    int memorySize; // size of memory space; min 4 bytes, Position 00 - 03; ie 55 is a hex value and means 84 
    int headerSize; // size of header space; min 4 bytes, Position 04 - 07; ie 47 (hex), so 71 (dec) same number as config-dialog
    int byte3; // version number 
    int byte4; // refreshing interval in msec
    ...

Moroever there are some areas in the memory, which contain some chars - how to cast those byte-values to chars and create words of them, currently I am only able to cast to int-values (see codesnippet 3)

int main(void){
    std::cout << "*** Start SharedMemory  ***\n";
    HANDLE hMapFile;
    ...
    Shm * pBuf = (Shm *) MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE); 
    std::cout << " Debug  memorySize " << ": " << dec << pBuf->memorySize << " (dec); " << hex << pBuf->memorySize << " (hex); " << &pBuf->memorySize << " (Adresse);\n";   // 84 Bytes
    std::cout << " Debug  headerSize " << ": " << dec << pBuf->headerSize << " (dec);       << hex << pBuf->headerSize << " (hex);\n";  // 71 Bytes
    std::cout << " Debug  byte3 " << ": " << dec << pBuf->byte3 << " (dec); " << hex << pBuf->byte3 << " (hex);\n";
    ... 

Upvotes: 1

Views: 1044

Answers (4)

Sam
Sam

Reputation: 7868

You may have aliasing and alignment problems. Read this for more details: strict aliasing and alignment

Basically, one can copy the memory into a local structure to avoid such problems:

Shm shmInfo;

memcpy(&shmInfo,&pBuf[shmInfoOffset],sizeof(shmInfo));

Upvotes: 3

Chris O
Chris O

Reputation: 5037

If your chars are packed 4 bytes into one int, then the below example might help. Note that endianess must be a consideration.

#include <string>
#include <iostream>

void appendCharsFromInt(std::string& inString, int intAsChars, int charCount)
{
    char someChars[4];
    memcpy(someChars, &intAsChars, sizeof(int));
    inString.append(someChars, charCount);
}

int _tmain(int argc, _TCHAR* argv[])
{
    int byte0 = 0x6c6c6548;
    int byte1 = 0x6f57206f;
    int byte2 = 0x00646c72;

    std::string completeString;

    appendCharsFromInt(completeString, byte0, 4);
    appendCharsFromInt(completeString, byte1, 4);
    appendCharsFromInt(completeString, byte2, 4);

    std::cout << completeString << std::endl;

    return 0;
}

Upvotes: 1

ern0
ern0

Reputation: 3172

If you deal with binary data, it's a good idea to write such functions:

char getByte(char* data,int offset);
void setByte(char* data,int offset,char value);
char getWord(char* data,int offset);
...
void setLongword(char* ptr,int value);

Then you can create functions which makes your code pretty and readable:

int getVersion(char* data) {
  return (int)getByte(data,8); 
}

Using macros for that purpose is also not a bad idea.

Upvotes: 1

Alexander
Alexander

Reputation: 758

Remark: casting files to struct is a bad idea. alignment, size of int, endian can differ in different systems.

Casting to any part of file:

const char  * pBuf = (const char *) MapViewOfFile...
const Mytype * myVar = (const Mytype *)(pBuf + myVarOffset);

So for strings just add offset to pBuf (pBuf + myVarOffset - is all you need) - and you get start pointer to string. (Hope there is a zero byte at the end of the string in the file.)

if your struct is supposed to have one buffer/string variable with unspecified length the following code may help:

struct MyStruct
{
   int size_of_string;
   char my_string[1]; //can be used as a long string of size size_of_string
};

note that sizeof(MyStruct) will not give you the right value in this case so you can not allocate this object with 'new' and on stack (use malloc/free instead).

I'd recommend you to read about serialization.

Upvotes: 3

Related Questions