I am using boost::make_shared for the first time to create objects pointed to by shared pointers. Mainly because our code was too slow and the single allocation really helped to improve performance.
After fixing some memory leaks "the hard manual way" I decided to implement a simple memory leak detector by overriding new operators for all relevant classes just for counting which objects are still alive at specific points in our application. I have implemented this several times before and was surprised to find my code no longer detects any objects.
I figured that all I had to do is override "placement new" instead of the "normal" operator new's because of the following from the boost website documentation for make_shared:
"Effects: Allocates memory suitable for an object of type T and constructs an object in it via the placement new expression new( pv ) T() or new( pv ) T( std::forward(args)... ). allocate_shared uses a copy of a to allocate memory. If an exception is thrown, has no effect."
My placement new is also not being called however. I have written a small test program to reproduce the behavior:
#include <iostream>
using namespace std;
#include "boost/shared_ptr.hpp"
#include "boost/make_shared.hpp"
class Test
{
public:
Test() { cout << "Test::Test()" << endl; }
void* operator new (std::size_t size) throw (std::bad_alloc) {
cout << "Test new" << endl;
return malloc(size);
}
void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw() {
cout << "Test non-throwing new" << endl;
return malloc(size);
}
void* operator new (std::size_t size, void* ptr) throw() {
cout << "Test non-throwing placement new" << endl;
return malloc(size);
}
};
void* operator new (std::size_t size) throw (std::bad_alloc) {
cout << "Global new" << endl;
return malloc(size);
}
int main() {
cout << "..." << endl;
boost::shared_ptr<Test> t1(boost::make_shared<Test>());
cout << "..." << endl;
boost::shared_ptr<Test> t2(new Test());
cout << "..." << endl;
return 0;
}
Which renders the following output:
...
Global new
Test::Test()
...
Test new
Test::Test()
Global new
...
I was expecting "Test non-throwing placement new" on the 3rd line of output. What do you think the behavior should be? Do you agree that according to documentation of make_shared it should call the placement new operator of my Test class? Or did I misunderstand it?
I could copy boosts implementation locally and add a call to the placement new operator of course. But, would that be appropriate, or would it violate the intended semantics of placement new?
Thanks in advance for your time and your help.