1

この構造の共有メモリがあります (codesnippet 1 を参照)。すべての値は 16 進値です。

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;
...

コメントでわかるように、どのバイトがどの情報を表しているかがわかります。とにかく、メモリを構造体にキャストします (codesnippet 2 を参照)。この構造体のプロパティは、現在整数値です。値 55 と 47 は、最初の 2 つのプロパティに格納されます。どうやら、「00」は無視され、メモリ全体をバイト単位で読み取ることができません。メモリをバイト単位で読み取るにはどうすればよいですか?

コードニペット 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
    ...

さらに、メモリにはいくつかの文字を含む領域がいくつかあります-これらのバイト値を文字にキャストして単語を作成する方法、現在、int値にのみキャストできます(コードニペット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";
    ... 
4

4 に答える 4

3

注意: ファイルを構造体にキャストするのは悪い考えです。アライメント、int のサイズ、エンディアンはシステムによって異なる場合があります。

ファイルの任意の部分へのキャスト:

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

したがって、文字列の場合は、pBuf にオフセットを追加するだけです (pBuf + myVarOffset - 必要なのはこれだけです)。文字列への開始ポインタを取得します。(ファイル内の文字列の末尾に 0 バイトがあることを願っています。)

構造体に、長さが指定されていない 1 つのバッファー/文字列変数があると想定されている場合は、次のコードが役立つ場合があります。

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

この場合、 sizeof(MyStruct) は正しい値を提供しないため、このオブジェクトを「new」およびスタックに割り当てることはできません (代わりに malloc/free を使用してください)。

シリアル化について読むことをお勧めします。

于 2013-11-09T20:59:11.497 に答える
3

エイリアシングとアラインメントの問題が発生する可能性があります。詳細については、これをお読みください:厳密なエイリアシングとアライメント

基本的に、メモリをローカル構造にコピーして、このような問題を回避できます。

Shm shmInfo;

memcpy(&shmInfo,&pBuf[shmInfoOffset],sizeof(shmInfo));
于 2013-11-09T21:04:03.827 に答える
1

バイナリ データを扱う場合は、次のような関数を作成することをお勧めします。

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);

次に、コードをきれいにして読みやすくする関数を作成できます。

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

その目的でマクロを使用することも悪い考えではありません。

于 2013-11-09T21:16:41.147 に答える
1

文字が 4 バイトで 1 つの int にパックされている場合は、次の例が役立ちます。エンディアンを考慮する必要があることに注意してください。

#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;
}
于 2013-11-09T21:38:24.550 に答える