Valik Posted November 9, 2004 Share Posted November 9, 2004 (edited) I got bored and did an experiment, this is the result. Does anybody else know why this works (This is obviously C++)? Should this win an award for obfuscation (Not my intent, but its pretty hard to read)? Does anybody besides me even know what the hell this does...?#include <iostream> class CTest { public: int m_n; CTest(int _n) : m_n(_n) { } virtual int method1() { std::cout<<"method1"<<std::endl; return 1; } virtual int method2() { std::cout<<"method2"<<std::endl; return 2; } }; int main() { CTest t(4); int **array = (int**)&t; std::cout<<"Ret: "<<(t.*(*(int (CTest::**)(void))(*array)))()<<std::endl; std::cout<<"Ret: "<<(t.*(*(int (CTest::**)(void))(++(*array))))()<<std::endl; std::cout<<"Val: "<<*(int*)++array<<std::endl; std::cout<<"\nPress {ENTER} to continue"<<std::endl; std::cin.get(); return 0; }Edit: I neglected to mention that this was done using VS 7.1 (.NET 2003). The results should be the same on any of Microsoft's compilers, the results may or may not be the same on other compilers (It could even be different between versions of VS, but I doubt it). Edited November 9, 2004 by Valik Link to comment Share on other sites More sharing options...
Guest Py7|-|[]/\/ Posted November 10, 2004 Share Posted November 10, 2004 Well, you've proved your point. Valik > I Link to comment Share on other sites More sharing options...
Administrators Jon Posted November 10, 2004 Administrators Share Posted November 10, 2004 I got bored and did an experiment, this is the result. Does anybody else know why this works (This is obviously C++)? Should this win an award for obfuscation (Not my intent, but its pretty hard to read)? Does anybody besides me even know what the hell this does...?No idea, mate. Deployment Blog: https://www.autoitconsulting.com/site/blog/ SCCM SDK Programming: https://www.autoitconsulting.com/site/sccm-sdk/ Link to comment Share on other sites More sharing options...
Henrik Posted November 10, 2004 Share Posted November 10, 2004 method1 Ret: 1 method2 Ret: 2 Val: 4 Press {ENTER} to continue The above is output from VC++ 6. Let's not tell the others how the code works. May I use your code tne next time I have to write a C++ coding standard? It will go in the 'don't do this' section. Ignorance is strength. Link to comment Share on other sites More sharing options...
Valik Posted November 10, 2004 Author Share Posted November 10, 2004 I expected Microsoft compilers would produce the same results. Jon (and others), when an object is layed out in memory (under MSVC), if the class contains virtual members, then the very first block of memory will be an array of pointers to the functions, otherwise known as the vtable. After that 4 byte block, the data members are stored. So the first two std::cout lines are accessing the vtable directly through the array of pointers. Instead of specifying the name to call a member through pointer (As AutoIt does internally), I'm skipping that step and just giving the address. Since the vtable is a pointer to an array of pointers, in the second line, I tell it to increment ot the second element in the array and then use that address to call the second function. The 3rd line prints the value in the data member (m_n). Since the members are layed out after the vtable, skipping over the vtable puts me to the first member. And, as Henrik said, this should not be done. Specifically because this is compiler dependant. This is the way Microsoft lays out an object in memory. Another compiler will likely be different and the code will break. This was just a fun experiment for me to see if I really did understand how an object was layed out in memory. However, in doing this, I thought up something applicable to AutoIt (Although it relates nothing to this code). Jon, the goal for doing function lookups is to use a binary search correct (Can't remember if this is in there yet or not...)? Well, what about taking that one step further. Why not cache functions in a second binary tree which is searched first? The benefit to this would be that in a long running script, all the functions could get cached and AutoIt would have to do even less work to find them (Again, I don't think this is implemented, but my memory is shoddy at times...) Link to comment Share on other sites More sharing options...
Administrators Jon Posted November 11, 2004 Administrators Share Posted November 11, 2004 I expected Microsoft compilers would produce the same results.Jon (and others), when an object is layed out in memory (under MSVC), if the class contains virtual members, then the very first block of memory will be an array of pointers to the functions, otherwise known as the vtable. After that 4 byte block, the data members are stored. So the first two std::cout lines are accessing the vtable directly through the array of pointers. Instead of specifying the name to call a member through pointer (As AutoIt does internally), I'm skipping that step and just giving the address. Since the vtable is a pointer to an array of pointers, in the second line, I tell it to increment ot the second element in the array and then use that address to call the second function. The 3rd line prints the value in the data member (m_n). Since the members are layed out after the vtable, skipping over the vtable puts me to the first member.And, as Henrik said, this should not be done. Specifically because this is compiler dependant. This is the way Microsoft lays out an object in memory. Another compiler will likely be different and the code will break. This was just a fun experiment for me to see if I really did understand how an object was layed out in memory.However, in doing this, I thought up something applicable to AutoIt (Although it relates nothing to this code). Jon, the goal for doing function lookups is to use a binary search correct (Can't remember if this is in there yet or not...)? Well, what about taking that one step further. Why not cache functions in a second binary tree which is searched first? The benefit to this would be that in a long running script, all the functions could get cached and AutoIt would have to do even less work to find them (Again, I don't think this is implemented, but my memory is shoddy at times...)Binary searches are currently in for builtin and user functions. Even for the 300 built in functions you only do about 7 string compares - it's lightning fast. Deployment Blog: https://www.autoitconsulting.com/site/blog/ SCCM SDK Programming: https://www.autoitconsulting.com/site/sccm-sdk/ Link to comment Share on other sites More sharing options...
SlimShady Posted November 11, 2004 Share Posted November 11, 2004 I converted a binary search function I found. Func BinarySearch($Arr, $target) ;Original Source: http://www.dcs.warwick.ac.uk/~zabin/dis.html Dim $low = 0 Dim $high = UBound($Arr) - 1 Dim $mid While $low <= $high $mid = ($low + $high) / 2 $mid = Int($mid) If $target = $Arr[$mid] Then ;//match Return $mid ElseIf $target < $Arr[$mid] Then ;//search low end of array $high = $mid - 1; Else ;//search high end of array $low = $mid + 1; EndIf WEnd Return $mid EndFunc Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now