Using void* to keep track of an external object.
-
Here is a void* problem to challenge you. I have a very large application A. Sometimes it needs to use a little application B. B instantiates an external dll I didn't write, we can call it G. B uses DllExport to export some functions I can call with DllImport. Whenever I call B it makes a new G and deletes it again. Fine. Now they changed the rules. I can only have one G. Easy, I think. Add an Init function to B's external interface, call it to instantiate my single instance of G. Return a void* to B, so whenever I want to call it it reuses the instance of B and thus of G. A is not allowed to know what happens in B, so the void* is perfect. I keep void* mPointerToB as a member of A. B has some internal classes, we can call one ClassM. So B contains a member ClassM mM. When I hop into B it runs for a while until it tries to call mM.function. Then I get a buffer overrun. So I googled and found this statement. "A void pointer cannot point to a class member in C++." Is my void pointer to B losing its internal objects along the way? Where can I find out more? Am I doing this in the wrong way? This is C++ in Visual Studio 2008. I use void* in other places to access pointers to things in Ada functions in the same way, so it should work, I think.
------------- Ave computer! Hackitura te salutat! (I just made this up. Just to show you can hack Latin as well as C++.)
-
Here is a void* problem to challenge you. I have a very large application A. Sometimes it needs to use a little application B. B instantiates an external dll I didn't write, we can call it G. B uses DllExport to export some functions I can call with DllImport. Whenever I call B it makes a new G and deletes it again. Fine. Now they changed the rules. I can only have one G. Easy, I think. Add an Init function to B's external interface, call it to instantiate my single instance of G. Return a void* to B, so whenever I want to call it it reuses the instance of B and thus of G. A is not allowed to know what happens in B, so the void* is perfect. I keep void* mPointerToB as a member of A. B has some internal classes, we can call one ClassM. So B contains a member ClassM mM. When I hop into B it runs for a while until it tries to call mM.function. Then I get a buffer overrun. So I googled and found this statement. "A void pointer cannot point to a class member in C++." Is my void pointer to B losing its internal objects along the way? Where can I find out more? Am I doing this in the wrong way? This is C++ in Visual Studio 2008. I use void* in other places to access pointers to things in Ada functions in the same way, so it should work, I think.
------------- Ave computer! Hackitura te salutat! (I just made this up. Just to show you can hack Latin as well as C++.)
RedSonja wrote:
When I hop into B it runs for a while until it tries to call mM.function. Then I get a buffer overrun.
What do you mean by 'hop into B', how are you executing the functions in B?
RedSonja wrote:
So I googled and found this statement. "A void pointer cannot point to a class member in C++." Is my void pointer to B losing its internal objects along the way? Where can I find out more? Am I doing this in the wrong way?
I'm not sure if this statement applies here. As you say you can use a void* to hold a pointer to anything, it is only when you use it to access the object it points to, that you may run into problems. If the void* points to an instance of a class then you would have to cast it to a CLASS* in order to use the object. Buffer overrun can be caused by a multitude of sins and if it is in the dll then you probably need to talk to the dll's developers for assistance.
-
RedSonja wrote:
When I hop into B it runs for a while until it tries to call mM.function. Then I get a buffer overrun.
What do you mean by 'hop into B', how are you executing the functions in B?
RedSonja wrote:
So I googled and found this statement. "A void pointer cannot point to a class member in C++." Is my void pointer to B losing its internal objects along the way? Where can I find out more? Am I doing this in the wrong way?
I'm not sure if this statement applies here. As you say you can use a void* to hold a pointer to anything, it is only when you use it to access the object it points to, that you may run into problems. If the void* points to an instance of a class then you would have to cast it to a CLASS* in order to use the object. Buffer overrun can be caused by a multitude of sins and if it is in the dll then you probably need to talk to the dll's developers for assistance.
Sorry, I was not very clear: I hop into B by calling a function B declares as DllExport, and A sees as DllImport. B has a dll and a lib and A can see them. This has always worked OK when I called it "fresh" every time. B's internal objects - static instances of B's classes - seem to be null when I go into B using the void* - I get the buffer overrun when I call functions of an internal object. (I am not allowed to use dynamic allocation "because the code is safety critical". This makes things very hard.) When I call B I import the stuff like this: DllExport int BDoWork( struct BigDataBlock1 *pBigDataBlock1, struct BigDataBlock2 *pBigDataBlock2, void* pB) I turn the void* back into a proper pointer like this: BWrapper* pmyB = (BWrapper*)pB; and it works OK, I can import data along with the pointer, and it seems to be alright, I can copy the data into B's internal structures. I use ASSERT when copying. B was written by myself. Respectable code always has a few bugs. I am sure there are still a few in there. What should I be looking for? It imports and handles very large amounts of data; I already had to cut the data into slices to avoid overflowing buffers on the dll call. I made it a dll so I could go into B with the debugger when debugging A. (Visual Studio is cool; it can even hop into Ada dlls, can you imagine?) You helped me a lot by saying void* should work the way I use it. Now I suppose the bug is inside B so I can concentrate there.
------------- Ave computer! Hackitura te salutat! (I just made this up. Just to show you can hack Latin as well as C++.)
-
Sorry, I was not very clear: I hop into B by calling a function B declares as DllExport, and A sees as DllImport. B has a dll and a lib and A can see them. This has always worked OK when I called it "fresh" every time. B's internal objects - static instances of B's classes - seem to be null when I go into B using the void* - I get the buffer overrun when I call functions of an internal object. (I am not allowed to use dynamic allocation "because the code is safety critical". This makes things very hard.) When I call B I import the stuff like this: DllExport int BDoWork( struct BigDataBlock1 *pBigDataBlock1, struct BigDataBlock2 *pBigDataBlock2, void* pB) I turn the void* back into a proper pointer like this: BWrapper* pmyB = (BWrapper*)pB; and it works OK, I can import data along with the pointer, and it seems to be alright, I can copy the data into B's internal structures. I use ASSERT when copying. B was written by myself. Respectable code always has a few bugs. I am sure there are still a few in there. What should I be looking for? It imports and handles very large amounts of data; I already had to cut the data into slices to avoid overflowing buffers on the dll call. I made it a dll so I could go into B with the debugger when debugging A. (Visual Studio is cool; it can even hop into Ada dlls, can you imagine?) You helped me a lot by saying void* should work the way I use it. Now I suppose the bug is inside B so I can concentrate there.
------------- Ave computer! Hackitura te salutat! (I just made this up. Just to show you can hack Latin as well as C++.)
Your casting of the
void*
looks correct and, as you say, allows you to process things as you would expect.RedSonja wrote:
Now I suppose the bug is inside B so I can concentrate there.
I think you probably answered your own question, something inside B may not be behaving correctly. Looks like some long hours stepping through the debugger - good luck.
-
Your casting of the
void*
looks correct and, as you say, allows you to process things as you would expect.RedSonja wrote:
Now I suppose the bug is inside B so I can concentrate there.
I think you probably answered your own question, something inside B may not be behaving correctly. Looks like some long hours stepping through the debugger - good luck.
Found it! Some external dll (G) I was using in B had an interface using CString. Since I am not allowed to use MFC, I redefined these to be string. I don't actually use these parts. Anyway, string is not the same as CString and this was causing an access violation, even though it compiled and linked, the rat. I solved this by taking a local copy of the G.h file of the external dll. In it I put includes so it could see CStrings. This actually makes the exclusion of MFC in my own code redundant, but I can't help that. The G people are not willing to work without MFC (neither was I actually). G also had some problems in its export functions, which are being repaired. We are pleased to find these bugs now and not after delivery.
------------- Ave computer! Hackitura te salutat! (I just made this up. Just to show you can hack Latin as well as C++.)