Suppose I got this in 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
In main.cpp, I casted the m_buffer in Message into Header type. The point is that I can access memory according to Header layout:
#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;
}
The Header* hdr is supposed to point to the same memory address as Message msg, and the m_primitive is supposed to be at the same address as Header* hdr, and the m_transNum is &m_primitive + 4.
However, this is the actual value:
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_primitive and m_transNum pointed to a completely random location and got garbage values! How can it happen? reinterpret_cast is supposed to change the layout according to class type, by casting to differnt type of pointer.
Also, if it returns a copy, the value of m_primitive should be 100, and m_transNum should be 1, because I memcpy into the buffer char* content of msg. But the values are wrong.
You are printing addresses of local stack variables to which you assigned values of your
Headerdata members. These addresses are not related to addresses of original variables.Try (see EDIT below with regard to
virtualdestructor)That’s under assumption there is no padding. But
enumfield size should beint, usually. So it’s 4 bytes and there is no padding. But check it to be sure.EDIT: I just saw you have
virtualdestructor inHeader. The above won’t work, since there is a pointer tovtableinsiderHeaderobject. Where it is placed is compiler specific. You can try some experimenting and adjust your offsets accordingly.