2012-02-14 64 views
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_buffer消息到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到緩衝器的msgchar* content。但價值觀是錯誤的。

回答

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個字節,沒有填充。但檢查它是確定的。

編輯:我剛纔看到你有virtual析構函數在Header。以上將不起作用,因爲有一個指針vtable內部人Header對象。放置位置是編譯器特定的。您可以嘗試一些實驗並相應地調整偏移量。

+0

我明白了。但是,我不明白,如果它返回一個副本,它不應該有垃圾值。當我將這些值輸出時,值不正確。 – Amumu 2012-02-14 04:49:00

+0

非常抱歉。 'FCPMsg'應該是'Message','MsgHeader'應該是'Header'。請修復它以保持一致。 – Amumu 2012-02-14 04:55:30

+0

Mark在他的評論中回答說。 – lapk 2012-02-14 04:55:40

2

您的​​和transNum()函數未返回對成員變量的引用,它們返回副本。當然,副本不會與原始地址相同。

+0

啊對了,但是如果它返回一個副本,我怎麼能在'm_primitive'和'm_transNum'中得到垃圾值? – Amumu 2012-02-14 04:43:23

+0

@Amumu,你的Header類中有一個虛函數,這意味着它將在佈局中有一個不可見的vtable指針,可能在前面。你對對象的二進制佈局做了太多的假設,並且遇到未定義的行爲。 – 2012-02-14 04:51:12

+0

謝謝。你是對的。 – Amumu 2012-02-14 05:55:07

相關問題