I have DLL and EXE app. DLL is registered in EXE. Then in EXE instance of class A is created as shared_ptr. Next, this instance is passed to the DLL and method example of this instance is called on DLL side.
class Result
{
//Some attributes e.g std::vector
}
class A
{
public:
A(){}
~A(){}
Result example(){
Result r;
//Fill data in r object....
return r;
}
}
The problem is that when example is called somewhere in DLL :
void someDLLMethod()
{
//a is a shared pointer of A class
{
Result r = a->example();
}//PROBLEM IS HERE DURING DEALLOCATING Result OBJECT
//some stuff...
}
It seems that the problem occurs during deleting r object. I understand when I will try to allocate some memory in EXE and then try to deallocate this memory in DLL then memory issues can occur, but in this case, Result object is copied from EXE to DLL. Also, vector stored in Result object doesn't contain any pointers so it should be deep copy of vector.
One solution is to allocate Result object in DLL, pass it as reference to called method and fill all necessary data, but I want to get copy as result.
Why this problem occurs? How it is possible to fix it? EXE and DLL are in this same solution of Visual studio and must be compiled with \MT or \MTd and there is no possibility to change it.
Memory for the vector is being allocated in the DLL and free'd in the exe as the vector is probably using move semantics in its return (or even just RVO) which just moves the pointer to the allocated internals. As you're using a static CRT this means the memory is being allocated with one crt and free'd with a different instance which leads to badness.
Short story - don't do this. Exposing C++ objects across DLL boundaries is bad. You should use a C interface or an interface that is designed for this - e.g. WinRT.
If you do choose to expose c++ objects across a DLL interface you must make sure that both the EXE and the DLL use the same version of the compiler and you link with /MD. If you can't use /MD you'll never get this to work reliably.
Sure you could pre-allocate the vector and fill it in in the call but that's just masking the issue until things inevitably change down the line.
Related
In my code I have a SoundManager class, which contains and operates on all the sounds for my game. This class needs to be instantiated and it's methods called by multiple other classes. However I wish for there only to be one set of sounds occupying memory, so in the interest of efficiency all of the assets are declared as static shared_ptrs.
#include "SoundManager.h"
static shared_ptr<ISoundEngine> sEngine;
static shared_ptr<ISoundSource> hoverSound;
static shared_ptr<ISoundSource> confirmSound;
static shared_ptr<ISoundSource> mainBGM;
static shared_ptr<ISound> bgmInterface;
SoundManager::SoundManager(void)
{
//first we need to create the irrKlang sound engine instance
if(!sEngine)
{
sEngine.reset(createIrrKlangDevice());
}
if(!hoverSound)hoverSound.reset(sEngine->addSoundSourceFromFile("Sounds/ButtonHover.mp3"));
if(!confirmSound)confirmSound.reset(sEngine->addSoundSourceFromFile("Sounds/ButtonConfirm.mp3"));
if(!mainBGM)mainBGM.reset(sEngine->addSoundSourceFromFile("Sounds/mainBGM.mp3"));
//set some default volumes
hoverSound->setDefaultVolume(1.0f);
confirmSound->setDefaultVolume(0.4f);
mainBGM->setDefaultVolume(0.5f);
}
SoundManager::~SoundManager(void)
{
}
This SoundManager is instantiated in my main() function and every time i need to load the title-screen (SoundManager is instantiated in this titlescreen class too). Initialising and destroying the title-screen over and over do not cause a problem. The static shared_ptrs objects are not destroyed as they are still in use by the main functions instance of SoundManager.
Now this all works fine in practice for running my game. However when it comes to exiting cleanly, when the static objects above are dismantled, unhandled runtime exceptions (access violations) are thrown at me. With VS2012's debugger pointing me to a line in memory.h.
private:
virtual void _Destroy()
{ // destroy managed resource
delete _Ptr; <<<<<<<<<The debugger points to this line
}
I was to understand that similar to obj-c, c++ shared_ptrs use reference counters to ensure that the objects aren't deleted until no object exists that require their use any more. I don't understand what could be causing these errors.
Maybe an important part I shouldn't omit: My game is exited via a call to exit(0); as close to the main() function as possible. I haven't taken any sort of action to cleanup the SoundManagers members before doing this, as I thought the shared_ptr's handled this.
Does anybody know what could be causing my cleaning up problem?
If you want to manually free a resource used by a shared_ptr you need to call reset. As for using static shared_ptr I don't think I get the reasoning. The whole point is that they do not copy of the resource around, so you will only have one resource.
Your are using the IRRKLang library. This library comes as a precompiled binary (dll if you are on windows). This library makes itself binary compatible by using pure virtual bases. This works, but you cannot delete an object for a library like that, because your program new/delete are different from the new/delete of the library. Those type of libraries provide a way to deallocate the memory, this this case drop.
To use shared_ptr etc you have to use a custom deleter. Take a look at Using custom deleter with std::shared_ptr to see how to do it and modify it to your own needs.
In your case since you are using Visual Studio 2012 you can probably do something like this
template<class T>
struct IrrDeleter{
void operator()(T* t){
t->drop();
}
};
then change all your reset lines to include the deleter, for example
sEngine.reset(createIrrKlangDevice(),IrrDeleter<ISoundEngine>());
Language : C++
Platform : Windows Server 2003
I have an exe calling a DLL.
EDIT :
(exe is not doing anything, it calls few global function which does everything related to DLL within DLL. It does not explicitly new any of DLL classes)
I allocate (new) the memory for class A within the DLL, it returns me a non-local heap pointer.
I tried to new other classes within the DLL (which are in DLL), "new" returns a valid heap pointer for them, its only Class A which is not being allocated properly.
I am on windows and validating the heap by this function call :
EDIT:
ClassA* pA = new ClassA();
_CrtIsValidHeapPointer ( (const void *) pA )
I am seriously confused why this only happens with new-ing Class A and no other class ?
(All Native Code)
FINAL EDIT :
it turned out to be a bad build. can't get it to reproduce in the new one... wasted 5 days on this :'(
Export only global functions from DLLs and call only exported functions and through v-tables. Your problem is only one of many caused by trying to export entire classes. DLLs aren't the same as .so libraries.
EDIT: Since the question now reveals that the class isn't exported, but all of this is observed inside the single DLL, going to suggest other possible causes.
Is the same pointer returned from new being tested, or could it be a pointer to a base sub-object? Did the allocation use new or new []? Either of these could cause the pointer to point into the middle of a heap block instead of the start.
If Class A overrides operator new then the memory for that class could be allocated in the DLL's copy of the C runtime. This would cause _CrtIsValidHeapPointer to return false - because your version of the C runtime library is using a different heap than the one in the DLL.
The value returned from _CrtIsValidHeapPointer is generally not reliable anyway (certainly, even though it may return TRUE it doesn't necessarily mean you can use the pointer). Why do you do this anyway?
Perhaps the class declares its own operator new that get storage from some mystery location?
e.g. The author of the class may have written:
class MyClass {
public:
void * operator new (size_t amt);
void operator delete(void *);
};
Then their operator new beats your operator new.
Either that or the DLL is built with /MTd while the executable uses /MD.
I'm having some trouble with a dynamically linked library calling my overloaded operator delete but not my operator new. My exe looks something like this:
class A {
public:
void func() {
t = dynLib::Type::CreateObject();
}
dynLib::Type t;
};
void main() {
A a;
a.func();
}
And then I have a statically linked library where I have my global overloaded operators
and the dynamically linked library that's causing the problem. Basically what happens is, the dynLib::Type type contains an std::vector to which it adds an element in its constructor. So the type looks something like this
class Type {
public:
Type() {
v.push_back( T() );
}
std::vector< T > v;
};
When func() is called, a new instance of Type is created, passed by value and then assigned to t. The operator= in work there copies over the std::vector also through its operator=. This in turn calls deallocate on the old std::vector in t, since it already had an element added in its constructor. This deallocate call ends up calling my operator delete. The problem is, my operator new was never called so it's deleting a pointer in a completely different memory space (memory logging shows this).
Now, I'm probably just missing something. Since class A above holds a dynLib::Type object, it might get constructed before my operator new (from the static library) gets linked. Is that even possible? I'm not quite sure at which point the constructor of the composed dynLib::Type is called. The dynamic library uses the default stl allocators so it doesn't do anything funky.
I've tried recreating the same situation without the dynamically linked library, just by having the Type class in my exe. This doesn't cause the issue though so it leads me to believe it must have something to do with the link order.
This is badness. You are in effect using STL objects across the DLL boundary. This is a big no-no and will continue causing headaches for you. The most likely source of linking problems is how the executable and the DLL use CRT. If one uses static (/MT) and the other is dynamic (/MD) you will see all sorts of weirdness, and overloaded operator new is usually the first one to glitch.
If the CRT is consistent across the board, then it should work, but it's still not recommended to use the DLL as though it's a static library.
Try to refactor the code so that you don't have to construct Type outside of the DLL, see if that makes it better.
I have a function foo() in dll A.dll, whose definition is as follows
vector<CustomObject> foo()
{
vector<CustomObject> customObjectCollection;
//code which populates customObjectCollection goes here
return customObjectCollection;
}
I am referring this method vector foo() of dll A from exe B
When i make a call to the function foo from B, I get an unhandled exception which says
"unhandled exception at
0x10487b3f(msvcp90d.dll) in B.exe"
0xC0000005: Access violation while
writing to the location 0xfdfdfdfd".
Note:type CustomObject does not implement copy constructor
When i tried to debug by attaching B.exe to A.dll, I found that inside method vector foo(), the vector gets populated without any problem but when the control returns to B.exe the valves in vector doesnot get copied !!!
Also, if method foo returns vector by reference , exception doesnot occur and B.exe receives an empty vetor.
what is the issue ?? Is it happening as I have not implemented copy constructor for CustomObject.
Any help is greatly appreciated
(Apologies for not articulating the question properly)
Thanks
jeel
This is a classic symptom of mismatched runtime libraries. You have to make sure that both the EXE and the DLL are linked to the dynamic C++ library (DLL version).
If one (or both) are linked with the static C++ runtime (LIB version), you'll get memory violations since there will be two instances of the runtime library with different address spaces.
First of all you should not return references to local objects declared on stack.
Second: there are requirements for elements to be able to be used in STL containers
1) Copy constructor
2) Assignment operator
3) Public destructor
There are more container specific (like sorting criterium for associative containers).
Copy constructor will be created as well as assignment operator (thanks to the compiler) so unless you explicitly hide them - your object has them (if you did not have copy constructor, compiler would complain).
But these implicit copy constructor and assignment operator may not be smart enough, so you may want to implement your own. For instance: lets say that you CustomObject in constructor creates an instance of some class with new and keep it as pointer to be destroyed in the destructor. Default copy constructor will make a shallow copy, so this will result in two objects holding the same pointer. Once one of them is destroyed, second one becomes inconsistent (it holds pointer that has already been released).
Final note: try not to return vector by value. A lot of copying is involved. Declare it in the caller on stack and pass it as reference to you foo.
Probably the safest way would be:
bool foo(vector<someclass*> &customObjectCollection)
{
//code which populates customObjectCollection goes here
return success
}
This way the calling program creates and maintains the vector so there's no need for copying. Caller would do
vector<someclass *> customObjectCollection;
foo(customObjectCollection);
Also, depending on what you are doing exactly, note the use of a vector of someclass pointers rather than someclass objects.
There are a number of possibilities here, and you haven't told us enough to determine which is most likely to apply.
One possibility is (semi-)unique to putting the code in a DLL. If you link the standard library statically, each module (EXE, DLL) gets its own memory management, including its own heap, so quite a few operations that try to transfer ownership of memory between one module and another will fail for (seemingly) strange reasons. The cure for this type of problem is usually to link to the standard library in a DLL for all your modules. This gives one copy of the standard library shared throughout the application, so passing ownership between modules doesn't cause a problem.
Another possibility is that your CustomObject class isn't handling copying appropriately. Since you've told us nothing about its internals, it's impossible for us to guess what you might need to do here.
I have a Windows DLL that at one point, returns a pointer to a class that is new'ed in the DLL's code. The class itself is a very thin wrapper around another class private to the DLL.
The calling executable has no problem working with this class, everything works fine, with the exception that when the calling executable tries to delete this class, I get a RtlValidateHeap error.
The reasons behind the error makes sense, the exe is trying to free memory on the DLL's heap, which is normally a bad thing.
I've come up with a few possible solutions:
Override the class's new operator to
allocate its memory off of the
executable's heap (provided I can
even get at that heap space). The wrapper is very thin, so I would only be allocating a few bytes from the exe's heap.
Provide a special destruction
function for this class (yuck).
Tell the user not to destroy the
class and live with leaks (no way!)
Is there a 'normal' way of doing this?
Most libraries that use this sort of functionality, whether C or C++, actually go with your second option - specific functions to get and release objects. It allows distribution of binary DLLs that don't have to be compiled identically to the calling executable.
I've seen this behaviour is when one of the binaries was built with debug options (which uses a debug heap that, amongst other things, uses RtlValidateHeap) and the other binary was built as a release binary. It might be worth checking that you only use like with like...
By far the easiest solution is (for the Visual Studio users) to use /MD or /MDd everywhere. If the CRT itself is in a DLL, there's only one heap. Your app and your DLL will share it.
Are you loading the DLL dynamically at runtime (by calling LoadLibrary), or are you linking to using a .lib file during the link phase of your exe? If you're dynamically loading/unloading the DLL then when the delete happens is the DLL still loaded? This is a classic problem for plug-in type designs and the typical solution is something like your second proposal - specific functions to create and delete the objects in question.
Option 2 is pretty normal, eg, a Release() method that just does a "delete this".
Note that normally the DLL doesn't have it's own heap as such - most DLLs will share the process heap (see GetProcessHeap), but often the language runtime will decorate or add padding around allocated memory - so the pointer your dll ends up with is not the same pointer the heap will expect in a call to free.
The general rule is always release allocated memory with the matching free function, from within the same module.
There are some exceptions though - memory you know has been allocated directly with HeapAlloc from a known heap can be freed from another module. GlobalAlloc/GlobalFree works across modules. Strings allocated with SysAllocString can be freed from another module. Memory you know has been allocated by the same DLL version of the runtime can be freed from another module, but I'd stay away from this.
On the DLL side, I would use something along these lines:
dll.h: /* all exported, included by dll user */
class dll_class {
public:
virtual void foo() = 0;
}
dll_class* create_class();
void delete_class(dll_class*);
dll.cpp: /* implement the creator and destroyer */
dll_class* create_class() { return new dll_class_imp(); }
void delete_class(dll_class* pClass) { delete pClass; }
dll_imp.h: /* implement the actual dll_class logic */
class dll_class_imp : public dll_class {
public:
virtual void foo() {...}
}
Now, on the DLL user's side, dll.h will be included, and used like so:
dll_class* pClass = create_class();
pClass->foo();
delete_class(pClass);
this way, there's a clear distinction between the DLL's part and the user's part. Being an abstract class, the user cannot create a dll_class using new; and it only makes sense you delete object similarly to the way you've created them, i.e. with the exported functions.
What looks like will work for us was to override the new and delete operators for the problem class. It turned out that there were 3 situations that could happen:
EXE new's object, EXE delete's object
DLL new's object, DLL delete's object
DLL new's object, EXE delete's object
The new and delete operators ensure that the DLL would be allocating and freeing all memory allocations. So far, so good - testing shows that the operators are always being used and the memory is coming from the DLL's heap.