• Advertisement
Sign in to follow this  

C++ "this" pointer off by 4 bytes

This topic is 3567 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to make an object that can create a message, and one of the elements of the message is a pointer to the object that created the message. OK? The problem is that when I set the message's pointer to "this" that pointer is off by 4 bytes! To the external world, the object is at the address 0x000dbda40 , but to the internal world "this" points to at 0x000dbda44 I am using inhereitance (lots of objects can create messages and they all derive from a base object), so that might be related to the problem. But the only workaround I can think of is to subtract those 4 bytes off, and I'm not really sure that's safe...

Share this post


Link to post
Share on other sites
Advertisement
first learn the difference between a bit and a byte.

account (and thread) closed till you have demonstrated this understanding.

contact a forum moderator for further detais.

Share this post


Link to post
Share on other sites
Quote:

account (and thread) closed till you have demonstrated this understanding.

contact a forum moderator for further detais.

I am not amused.

This is not the lounge. If you're not going to do anything but make insepid 'jokes' and pretend like you're a moderator, do not post. I don't expect to see any more off-topic baiting in this thread.

Share this post


Link to post
Share on other sites
Quote:

I am using inhereitance (lots of objects can create messages and they all derive from a base object), so that might be related to the problem. But the only workaround I can think of is to subtract those 4 bytes off, and I'm not really sure that's safe...

It's not.

There are cases that can cause the this pointer to differ for what is the same aggregate object (for example, multiple inheritance situations, or if you are in the constructor, as the derived classes are not yet constructed).

Can you show us the relevant code? It will be easier to provide some direction.

Share this post


Link to post
Share on other sites
Quote:
Original post by polaris2013
I'm trying to make an object that can create a message, and one of the elements of the message is a pointer to the object that created the message. OK?

The problem is that when I set the message's pointer to "this" that pointer is off by 4 bytes! To the external world, the object is at the address 0x000dbda40 , but to the internal world "this" points to at 0x000dbda44

I am using inhereitance (lots of objects can create messages and they all derive from a base object), so that might be related to the problem. But the only workaround I can think of is to subtract those 4 bytes off, and I'm not really sure that's safe...


May be similar to a problem I had. Long story short, it was because the compiler was using different packing rules across different files, meaning that the compiler had a different idea of what the "this" pointer was supposed to be.

Share this post


Link to post
Share on other sites
Maybe it will help if I post some code (forgive the hungarian, this is for windows and I wanted to be consistent)

[source=cpp]
E_VAL CObjectBase::QueueRequest(MESSAGE msg)
{
if(g_pObjectMessageQueue == NULL) return RET_ERROR;

CMessage* vmsg = new CMessage;
vmsg->m_pRequestingObject = this;
vmsg->m_pRequestingObject = &*this;
vmsg->m_pRequestingObject = static_cast<CObjectBase*>(this);
vmsg->m_pRequestingObject = static_cast<CObjectBase*>(&*this);
vmsg->m_pRequestingObject = dynamic_cast<CObjectBase*>(this);
vmsg->m_pRequestingObject = dynamic_cast<CObjectBase*>(&*this);
vmsg->m_wRequestingObjectType = Get_Type();
vmsg->m_wRequestingObjectMessage = msg;
g_pObjectMessageQueue->QueueRequest(vmsg);

return RET_OK;
}






Yes, I went bonkers with typecasting to see if one of them would work. They don't.
As was suggested by this article:
http://carcino.gen.nz/tech/cpp/multiple_inheritance_this.php

edit: some more code (also slightly modified the code that was above before the edit)-

here's the message handler (yea, I know this is unsafe casting, but I don't see any other way to do it)
[source=cpp]
void CGame::UpdateState(DWORD msec)
{
//iterate through requests until NULL is returned
while(m_pMessageQueue->PeekRequest())
{
CMessage* msg = m_pMessageQueue->PopRequest();
CRegion* r;
switch(msg->m_wRequestingObjectMessage)
{
case MSG_MAPCHANGE:
r = (CRegion*)msg->m_pRequestingObject;
ChangeMap(r->Get_PointerIndex());
break;
}
}
}





Here's an example call:
[source=cpp]
CRegion* region;
//allocate it somehow
region->QueueRequest(MSG_MAPCHANGE);





Also SC4Freak, I'm not doing any manual byte aligning so I think it is unlikely to be the same as your problem.

edit #2: The problem is that the wrong address is stored in CObjectBase::QueueRequest(), because the this pointer is not the same as the pointer in the example call

edit #3: now that I wrote it all down like that I see an obvious workaround that avoids using the "this" pointer, but I would still like to know why this happened for future reference.

[Edited by - polaris2013 on July 12, 2008 9:03:01 PM]

Share this post


Link to post
Share on other sites
Off hand, I can't see any reason why "this", "region", and "r" in

CRegion* region;
//allocate it somehow

vmsg->m_pRequestingObject = this;

r = (CRegion*)msg->m_pRequestingObject;


would be different. So either I missed something or there is something you have not showed us.

At the very least, when you call

region->QueueRequest(...)


"region" and "this" within the function must have the exact same value. (I havent worked with a bazillion compilers but I don't know any that don't implement "this" that way and I don't event want to imagine how it could be implemented any other way)

However it's possible that something inadvertently changes the value of "m_pRequestingObject" after you have set it to "this"

Share this post


Link to post
Share on other sites
Are you using multiple inheritance with "multiple" virtual functions? In that case this is perfectly valid.

A pointer of a derived class with multiple virtual tables cast down to one of the base classes will have a slightly offset address to make up for the "other" virtual table.

Compare the type of this to the type of m_pRequestingObject.

Share this post


Link to post
Share on other sites
If you are upcasting the 'this' pointer, you can get the behavior you are describing (as other people have mentioned).

Here is a very quick example that shows the same problem:


#include <iostream>
using std::cout;
using std::endl;

class A
{
public:
virtual void functionone() {}

};

class B
{
virtual void functiontwo() {}

};

class C : public A, public B
{
public:
C()
{
class B* b = this;
cout << b << endl;
}
virtual void functionone() { }
virtual void functiontwo() { }
};

int main(int argc, char** argv)
{
C* c = new C();
cout << c << endl;
delete c;
return 0;
}





At least in VS2005, this shows a 4 byte difference due to casting 'this' up to a B*, because to do so it must skip over the memory occupied by A and return a pointer to the B portion of C. If A actually had some member variables, the difference in the addresses would be even larger, but currently all A has is its vtable pointer.

Share this post


Link to post
Share on other sites
Try this:

void *creator = dynamic_cast<void *>(this);


This returns a pointer to the address of the most derived object (assuming you have virtual functions in your hierarchy).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement