Archived

This topic is now archived and is closed to further replies.

GeniX

compiler building incorrect vtables?

Recommended Posts

Hey all, In some code I am trying to get working, I have encountered an issue. I had it previously occur under VC6, but after changing it to a less OO method, I got it working. Changing it back to the method used before, it surpisingly continued working. Now I am under .net, and the same problem re-occurs. The problem is this: I have a pointer to a base class. Knowing that the base class is in fact an instance of a derived class, I typecast it to the derived class. I then access public methods on it. Nothing too new about that. However, in *some* source files, I find that calls to functions on the derived class step into the *wrong* function in the class. Basically I call function a() on the class, but the compiled code thinks its calling a(), but jumps to the address of b() instead! You might say the vtable is being trashed, but heres the killer: In other cpp files, the correct function is called (on the same instance of the object in RAM, typecast from the same base class). And, after many hours of investigation, I found that if I change the order of my #include directives, it fixes the problem. I am 100% sure that the class name, and function names are unique - even in the context of standard C and C++ libs. So the order of the includes should not matter. Because it calls the wrong function in the class, it complains that ESP was not saved across the call (presumeably since there are, at minimum, parameter descrepancies). If you have experienced this issue previously, please inform me on your solutions. I have tried messing with some of the project C++ compile settings. No luck. While I could change the include directives order around, this is not a workable solution as it is very likely that with more includes being added/removed, the problem will continue to re-occur and be a continual slow-down. regards, GeniX www.cryo-genix.net

Share this post


Link to post
Share on other sites
I think we''d have to see more information (code snippits?) to help you debug this. I''ve been using VC6 for years to do professional programming (and VC.NET for one year) and I''ve never seen this sort of thing, assuming all classes were defined correctly, virtual was used correctly, etc.

Share this post


Link to post
Share on other sites
How are you performing the cast? Are you using the correct one of the four c++ casts, dynamic_cast? Or are you just doing a C-style cast?

It would be nice to see the code

Maybe look at this gotw.

[edited by - petewood on March 4, 2003 5:52:18 PM]

Share this post


Link to post
Share on other sites
I am sorry, but I cannot paste code. I am working on the project, but it is not mine.

The short of it is that I create the object, and then assign it to the base class pointer (the created object is the derived class).

And after each little bit of code, I pasted 4 lines that typecast (C-style) the base class back to the derived class, and try call one of the accessor methods. I did this thinking something was being trashed, and at some point the correct function would cease being called, and the wrong one would be.

I found that I could follow the objects life-time as execution passed between various function calls whose source resides in different cpp files. The odd thing was that when execution entered code compiled from certain cpp files, it would call the incorrect function, but when execution passed into code generated from other cpp files, it would call the correct function on the object.

So Im guessing the object itself is not being trashed, but rather the compiler, depending on include hierarchy or perhaps other directives resolves the function addresses differently in some cpp files.

As said, in the instance which I have ''fixed'', changing include order fixed the issue. There is another instance of it, which is why Im trying to find out *why* its happening.

Sorry that I cant provide much more than this. Im just hoping someone has experienced this before, and can offer a solution.



regards,

GeniX

www.cryo-genix.net

Share this post


Link to post
Share on other sites
Sounds like more of a linker problem than a compiler problem. Does the linker issue any warnings when you build? Are you making use of DLLs in the program? Are you ensuring the compiled program uses the same version of the C runtime if you''re passing data types whose size might change based on this?

Share this post


Link to post
Share on other sites
The c-style cast can mess things up. Use dynamic_cast and check that it worked at runtime.

When I asked for code I just meant the line where you do the cast.

[edited by - petewood on March 5, 2003 3:23:02 AM]

Share this post


Link to post
Share on other sites
I''ve noticed that on large projects, MS Dev can get confused about the dependency tree and not compile code that should be compiled (i.e. you change the header and the .cpp''s that #include that header aren''t recompiled). This also happens with makefiles that don''t automatically generate dependencies.

I say this because your problem looks like you''ve altered the class definition (the .h file) and the compile process hasn''t compiled all the relevant source files. Which means, some of your source is using vtables from a previous version of the class definition so will jump to the wrong place.

Try a forced rebuild all and see if it sorts out the problem.

Also, using DLLs will add to the above problem is the class is shared between the main program and the DLLs.

Skizz

Share this post


Link to post
Share on other sites
Thanks for the replies all, but it is solved (after wasting a day of my time).

Petewood:
When casting from a base pointer to a derived pointer (when you are sure the class is an instance of the derived pointer), then C-style cast shouldnt offer any problems. Thanks for the suggestion tho'', but it was not the case.

gmcbay:
Your point is well taken. It does sound more linker related, but given the unusual solution, Im still not sure *where* it was going wrong.

skizz:
That is true - I have had issues due to the compiler not compiling the .h files. Its screwed dependancy tree has caused many a clean build. But this was not the case.


The case was that I opened the old VC6 project, and it offered to convert it to the newer .sln style. I opted yes, and the conversion seemed problem free - all the project settings, even source control mappings and such were preserved.

But after exausting all my know-how and other alteratives, I finally make a new .net project (empty) from scratch, re-added all the files by hand and set up the project dependancies and settings again.

In short, I made a *new* project. It now works without a hint of a problem. .net''s new runtime debugging even picked up an issue that VC6 hadnt!

I now have the lengthy task ahead of me that involves getting the .net project as nicely sorted as the older VC6 project. *sigh*



regards,

GeniX

www.cryo-genix.net

Share this post


Link to post
Share on other sites
Submitting to these forums often has oddities - internal server errors, and such. One is never certain whether the reply is indeed there - the reply count doesnt seem to include my last comment, so I post this to see if it fixes.

PS: Magick Vol 5, DJ Tiesto - good music to code to

Share this post


Link to post
Share on other sites