If I use the new
keyword in my library (which is built differently than my main app), when I delete it in my main app with delete
, is there a chance that I may get a crash/error?
yes indeedy. In particular you see problems with debug/release heaps being different, also if your library uses placement new, or any custom heap you'll have a problem. The Debug/Release issue is by far the most common though.
It depends. If you're talking about a static library, then you'll probably be OK -- the code will run in the same context as the main program, using the same C++ runtime library. This means that new
and delete
will use the same heap.
If you're talking about a shared library (a DLL), then you probably won't be OK. The code running in the DLL might be using a different C++ runtime library, which means that the layout of the heap will be different. The DLL might be using a different heap altogether.
Calling delete
(in the main program) on a pointer allocated by the DLL (or vice versa) will lead to (at best) an immediate crash or (at worst) memory corruption that'll take a while to track down.
You've got a couple of options. The first is to use the "factory method" pattern to create and delete these objects:
Foo *CreateFoo();
void DeleteFoo(Foo *p);
These should not be implemented in the header file.
Alternatively, you can define a Destroy
method on the object:
class Foo
{
~Foo();
public:
virtual void Destroy();
};
...again, don't implement this in the header file. You'd implement it thus:
void Foo::Destroy()
{
delete this;
// don't do anything that accesses this object past this point.
}
Note that the destructor for Foo is private, so that you have to call Foo::Destroy
.
Microsoft COM does something similar, where it defines a Release
method that deletes the object when its reference count drops to zero.
yes indeedy. In particular you see problems with debug/release heaps being different, also if your library uses placement new, or any custom heap you'll have a problem. The Debug/Release issue is by far the most common though.
Yes, you will. A simple solution is to provide Create and Delete functions in your library that can be called from the main application. The Create function will perform the new and return a pointer, which is later passed into the Delete function for deletion.
It is a problem that I have only seen on Windows.
The Unixish systems do not make a habit of forcing shared libraries to link to different versions of the same library within the same program and all loaded symbols are visible globally. That means that if an object is allocated in one part of code and deleted in another, both are using the same system library to do it.
I have to say, this problem Windows creates with its various C runtime DLLs is really annoying and unnatural to a C programmer. Look at the C library; it has functions like strdup that malloc the string and expect the programmer to call free() on it. But do the same thing in your own library on Windows and just wait for the explosion. You'll have to wait, too, because it won't happen during development but only after you've given the compiled DLL to some other poor sap.
Old New Thing has covered this before. He also gives a list of Microsoft's main solutions.
You're quite right that there's a problem there, but for most cases there's an even simpler solution than the other answers (so far) have proposed. You can continue using new and delete freely -- all you need to do is overload new and delete for each class in your library that might be used across DLL boundaries.
Personally, I just defined a simple class to provide the needed functionality:
class NewDelete
{
public:
void *operator new (size_t size);
void operator delete (void *memory);
void *operator new (size_t size, void *ptr);
void operator delete (void *memory, void *ptr);
};
As long as those four member functions are all defined in the same DLL, then any class which derives from this class is automatically "DLL-safe" -- new and delete can be used normally on them without worrying about DLL boundaries.
© 2022 - 2024 — McMap. All rights reserved.