在Linux上使用c++时,我遇到了一个问题。
我有一个基本的Message类,如下所示:
class MsgBase
{
public:
MsgBase( unsigned int msgid );
map < unsigned int, MSGIEBase* > messageIE_Map; // map for IEs
unsigned int messageId; // 32 bit message id
};类Der1从MsgBase派生而来,如下所示:
class Der1 : public MsgBase
{
public:
Der1 ();
virtual ~Der1 ();
// IEs
MSGIE_UINT32 ueId;
MSGIE_String configFileName;
};这里,MSGIE_UINT32和MSGIE_String是从MSGIEBase派生的类,因此它们的地址可以存储在上面基类中定义的映射中。当构建Der1时,ueId和configFileName的地址被存储在映射中。在这里,如果我打印地图的大小(通过gdb和在程序中),它就是24。_M_header = 16,_M_node_count = 4,_M_key_compare = 1,我想是3字节填充。
在这里之前一切都很好。现在,Der1对象指针被放在一个事件对象中,事件被post到一个队列中。事件类如下所示:
class Event
{
public:
MsgBase* msgPtr;
};另一个线程从队列中删除事件,提取msgPtr并将其强制转换为Der1指针,这就是问题开始的地方。
在这里,如果我在程序中打印地图的大小,它是21。这意味着MsgBase类中的下一个成员,即messageId的地址被移位了3个字节,因此messageId的值完全改变了。(当通过gdb查看时,地址仍然完好无损,映射的大小也是如此,即24 )。
据我所知,这是一个单词对齐问题,但是为什么在不同的函数中内存对齐不一致,以及为什么类成员的地址在类的内存已使用new分配时发生变化。我使用的是Linux 2.6.27。,gcc 4.1.1版。、RHEL-4。
发布于 2011-08-15 04:54:48
为了排除非虚拟析构函数/复制/赋值问题,请在MsgBase中添加以下内容
public:
virtual ~MsgBase();
private:
MsgBase(MsgBase const& other);
MsgBase& operator=(MsgBase const& other);发布于 2011-08-15 07:42:19
我将尝试一步一步地提供所有必需的信息:
信息1:相关代码。
//Step 1: Create msg and fill message Id
MsgBase*msgPtr = new Der1();
// C'tor of Der1 is as follows:
Der1::Der1 ()
: MsgBase ( ATS_SUTD_EPCTESTER_ATTACH_SCENARIO_MsgId ), // msgid is 13( 0xd )
ueId ( IE_UE_KEY, "UE", false ),
configFileName ( IE_CONFIG_FILE_NAME_KEY, "Configuration File Name", false )
{
// Insert the IEs in the map
this->addIEEntry ( IE_UE_KEY, &ueId ); // this puts entries in the map
this->addIEEntry ( IE_CONFIG_FILE_NAME_KEY, &configFileName );
}
// Step 2: Declare event and post the event
Event* event = new Event ( eventId, "Event" );
event->setData( msgPtr, hdr);
// check the message id at this stage (
cout << "msgId = " << ( ( (Der1* )msgPtr )->messageId )<< endl; // Here it comes out
// to be 0xd which is correct
// post the event
AppClass::getInstance()->addEventAndSchedule ( event );
//The queue is a member of AppClass and has been defined as
std::list <EventBase* > eventQueue;
// The code which inserts data into the queue is as follows:
bool AppClass::addEventAndSchedule ( EventBase* ev )
{
if ( ev == NULL ) return false;
this->eventQueueMutex.acquireLock();
this->eventQueue.push_back( ev );
this->eventQueueMutex.releaseLock();
// Submit Job to Scheduler
bool status = JobScheduler::getInstance()->scheduleJob( this );
return status;
}
// The event class is
class Event: public EventBase
{
public:
Event ();
virtual ~Event ();
Event ( int evId );
Event ( int evId, string evName );
MsgBase* getMessagePtr ();
void setData ( MsgBase* mPtr, Header* hPtr )
private:
// Prevent copying
Event& operator= ( Event& ev );
Event ( Event& evBase );
MsgBase* msgPtr;
Header* hdrPtr;
};
void Event::setData ( MsgBase* mPtr, Header* hPtr )
{
this->msgPtr = mPtr;
this->hdrPtr = hPtr;
}
Step 3 : Extract the event and re-print the message Id
// The code which extracts data from the queue is as follows:
void AppClass::process ()
{
EventBase* beventPtr = NULL;
this->eventQueueMutex.acquireLock();
if ( !this->eventQueue.empty() )
{
beventPtr = (EventBase* )( this->eventQueue.front() );
this->eventQueue.pop_front();
}
else
{
isQueueEmpty = true;
}
this->eventQueueMutex.releaseLock();
Event* eventPtr = ( Event* )beventPtr ;
Der1* msgPtr = (Der1* )( eventPtr->getMessagePtr()) ;
cout << "msgId = " << msgPtr->messageId << endl; // This value
//comes out to be incorrect it is now 0xd000000 i.e. a 3 byte shift
}信息2:确切的问题。确切的问题是“messasgeId”在转换过程中发生了变化。最初它是0xd,但从队列中弹出后,它变成了0xd000000。正因为如此,所有的处理都停止了。在程序中打印时,此参数的地址也从0x82bd7cc更改为0x82bd7c9。但是,从gdb上看,它仍然是0x82bd7cc,值仍然是0xd。
信息3:编译器标志。编译器标志对于所有文件都是相同的,它们是:-O0 -g3 -Wall -fmessage-length=0
https://stackoverflow.com/questions/7058127
复制相似问题