kailang.deng
12/10/2008 6:36:00 AM
On Dec 10, 12:05 am, "jason.cipri...@gmail.com"
<jason.cipri...@gmail.com> wrote:
> On Dec 9, 8:17 am, kailang.d...@gmail.com wrote:
>
>
>
>
>
> > Hello,everybody
>
> > I have a program as follows.
>
> > class ClassA
> > {
> > public:
> > int buff[1];
> > virtual void test(void) {cout<<"ClassA::test()"<<endl;}
>
> > };
>
> > void entry(void)
> > {
> > cout<<"Hey,i am here!"<<endl;
>
> > }
>
> > ClassA Obj1,Obj2,*pObj;
>
> > int main()
> > {
> > pObj=&Obj2;
>
> > //Test group 1
> > Obj2.test();
> > pObj->test();
>
> > //Obj1.buff[1] covers the pvftable field of Obj2
> > int vtab=(int)(entry);
>
> You should use reinterpret_cast<>, and you have to be able to
> guarantee that an int is large enough to hold a function pointer, or
> this conversion is undefined.
>
Using reinterpret_cast<> is a good suggestion.The size of a function
pointer and the size of int type are both 4 bytes in MSVC.So,i think
that an int can hold the pointer.
> > Obj1.buff[1]=(int)&vtab;
>
> You can't rely on the virtual table having a specific layout, or being
> in a specific place, or holding certain types of data (and certainly
> not on it being able to use a function pointer cast to an int), or the
> layout of global variables in memory being somehow related to the
> order you've declared them in.
>
> It appears that you are attempting to do this:
>
> ClassA Obj1, Obj2;
>
> In hopes that Obj2 will always come after Obj1 in memory, and that
> Obj2's vtable entries come immediately after the data for Obj1, and
> that by accessing past the end of Obj1's data array, you're
> overwriting the appropriate vtable entry with valid data. All of that
> is *entirely* outside the scope of C++, and the program is undefined.
> Any weird behavior you see is arguably off-topic here.
>
> You'd be better served by doing whatever it is you're trying to do
> using normal, well-defined concepts like inheritance, or function
> pointers. This is one way to do what you're trying to do, with
> inheritance:
>
> class ClassA {
> public:
> virtual void test () {cout<<"ClassA::test()"<<endl;}
>
> };
>
> class ClassB : public ClassA {
> public:
> void test () {cout<<"Hey,i am here!"<<endl}
>
> };
>
> ClassA Obj1;
> ClassB Obj2;
>
> int main () {
> Obj1.test();
> Obj2.test();
>
> }
>
> Using a function pointer can give you the same behavior as the
> intended behavior of your original program (I did not test or compile
> this):
>
> void default_test () { ... }
> void entry () { ... }
>
> class ClassA {
> public:
> void (* test) ();
> ClassA () : test(default_test) { }
>
> };
>
> void elsewhere () {
> ClassA obj;
> obj.test = entry;
> obj.test();
>
> }
>
> Using a functor would give you more flexibility. There are many other
> ways to accomplish the same sort of thing as well, all that *are*
> defined by C++.
>
Thanks Jason for the two good suggestions especially using a function
pointer from which I learn a lot. I will consider it in the later.
> Why are you trying to do it this way, anyways?
I just want to explore the inner of C++ VPTR by smashing it. But i
don't know the way isn't defined by C++.
Finally, thanks a lot for your detailed answers and the suggestions.
Regard~
-Bruce
>
> Jason
>
>
>
>
>
> > //Test group 2
> > Obj2.test();
> > pObj->test();
>
> > return 0;}
>
> > The result is:
> > ClassA::test()
> > ClassA::test()
> > ClassA::test()
> > Hey,i am here!
>
> > Then,it is the point that i am confused.
> > In my viewpoint,after covering the pvftable field of Obj2,both Obj2
> > and pObj should invoke the function entry and print "Hey,i am here!".
>
> > Then i disassemble the program,it likes as follow
> > Obj2.test();
> > 00401202 mov ecx,offset Obj2 (0042e168)
> > 00401207 call @ILT+20(ClassA::test) (00401019)
> > pObj->test();
> > 0040120C mov eax,[pObj (0042e158)]
> > 00401211 mov edx,dword ptr [eax]
> > :
> > :
> > 0040121B call dword ptr [edx]
>
> > These disassembly codes may have explain the print result.
> > But can anybody explains the differences between the object and the
> > pointer points to object?
> > Thanks a lot!
>
> > -Bruce- Hide quoted text -
>
> - Show quoted text -- Hide quoted text -
>
> - Show quoted text -