0

假设我在 Message.h 中得到了这个:

#ifndef _MESSAGE_H_
#define _MESSAGE_H_
#include <stdio.h>
#include <string.h>
enum PRIMITIVE{
      MESSAGE_1 = 100,
      MESSAGE_2,
};

enum { MSG_SIZE_IN_BYTES = 1024 };

class Header{
    protected:
        Header(PRIMITIVE prim, u_int32 transNum) : m_primitive(prim), m_transNum(transNum) { }
    public:
        // access
        PRIMITIVE primitive() const { return m_primitive; }
        u_int32 transNum()  const { return m_transNum; }
        virtual ~Header(){}
    private:
        PRIMITIVE m_primitive;
        u_int32 m_transNum;
    };

class Message
{
public:
    Message() { reset(); }
    // access
    char* addr() { return reinterpret_cast<char*>(m_buffer); }
    const char* addr() const { return reinterpret_cast<const char*>(m_buffer); }
    u_int32 size() { return sizeof(m_buffer); }
    // msgs
    Header* msgHeader() { return reinterpret_cast<Header*>(addr()); }
    const Header* msgHeader() const { return reinterpret_cast<const Header*>(addr()); }
    // modify
    void reset() {
        memset(&m_buffer, 0, MSG_SIZE_IN_BYTES);
    }
private:
    u_int64 m_buffer[MSG_SIZE_IN_BYTES / sizeof(u_int64)];
};
#endif

main.cpp中,我将m_bufferin Message 转换为Header类型。关键是我可以根据Header布局访问内存:

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int main(int argc, char *argv[]){
    Message msg;

    char* content = msg.addr();
    int prim = 100;
    int trans_num = 1;

    memcpy(content, &prim, 4);
    memcpy(content+4, &trans_num, 4);       

    const Message::Header* hdr = msg.msgHeader();
    Message::PRIMITIVE hdr_prim = hdr->primitive();
    u_int32 hdr_transNum = hdr->transNum();

    cout << "Memory address of Message: " << &msg << endl;

    cout << "Memory address of Message buffer: " << (void*) msg.addr() << endl;             
    cout << "Memory address of content: " <<  content << endl;      

    cout << "Memory address of Header: " << hdr << endl;
    cout << "Memory address of m_primitive in Header: " <<  &hdr_prim << endl;
    cout << "Memory address of m_transNum in Header: " <<  &hdr_transNum << endl;

    cout << "Primitive in Header: " << prim << endl;        
    cout << "Trans num in Header: " << transNum << endl;
}

Header* hdr应该指向与 相同的内存地址,Message msg并且m_primitive应该与 位于相同的地址Header* hdr,并且m_transNum&m_primitive + 4

但是,这是实际值:

Memory address of Message: 0x699520

Memory address of Message buffer: 0x699520
Memory address of content: 0x699520

Memory address of Header: 0x699520
Memory address of m_primitive in Header: 0x7f2ec2f2738c
Memory address of m_transNum in Header: 0x7f2ec2f27388

Primitive in Header: 1
Trans num in Header: 1953719668

m_primitivem_transNum指向一个完全随机的位置并得到垃圾值!怎么会发生?reinterpret_cast应该通过转换为不同类型的指针来根据类类型更改布局。

另外,如果它返回一个副本,则 的值m_primitive应该是 100,并且m_transNum应该是 1,因为我memcpy进入char* contentmsg. 但价值观是错误的。

4

2 回答 2

2

您的primitive()andtransNum()函数没有返回对成员变量的引用,而是返回了一个copy。当然,副本不会与原始地址相同。

于 2012-02-14T04:40:15.003 回答
1
Message::PRIMITIVE hdr_prim = hdr->primitive();
u_int32 hdr_transNum = hdr->transNum();

...

cout << "Memory address of m_primitive in Header: " <<  &hdr_prim << endl;
cout << "Memory address of m_transNum in Header: " <<  &hdr_transNum << endl;

您正在打印为Header数据成员分配值的本地堆栈变量的地址。这些地址与原始变量的地址无关。

尝试(有关virtual析构函数,请参见下面的编辑)

const Message::Header* hdr = msg.msgHeader();
Message::PRIMITIVE * hdr_prim = ( Message::PRIMITIVE * ) hdr;
u_int32 * hdr_transNum = ( u_int32 *) ( ( ( char * ) hdr ) + sizeof( Message::PRIMITIVE ) );

...

cout << "Memory address of m_primitive in Header: " <<  hdr_prim << endl;
cout << "Memory address of m_transNum in Header: " <<  hdr_transNum << endl;

这是假设没有填充。但是enum字段大小通常应该是int。所以它是 4 个字节并且没有填充。但请检查以确保。

编辑:我刚刚看到你virtualHeader. 以上将不起作用,因为有一个指向vtable内部Header对象的指针。它的放置位置是编译器特定的。您可以尝试一些实验并相应地调整您的偏移量。

于 2012-02-14T04:44:24.080 回答