I need to provide a utility function where both memory allocation and object construction take place and the user gets the pointer in return. Similarly, there is a need to provide a utility function for deallocation and destruction also.
Here is what I implemented: (I have not implemented for array type though)
#include <cstdlib> // for malloc
#include <iostream> // for cout
#include <string> // for memset
// C++ class with some initial state x = 10
class SomeClass {
public:
SomeClass() : x(10) {}
int x = 0;
};
template<typename T, typename ... Args>
inline T* MY_MODULE_NEW(Args&&... args) {
// some custom allocator logic here which allocates just raw memory
// for example purpose just use malloc
void *p = malloc(sizeof(T));
memset(p,0,sizeof(T));
T* t = new(p) T(std::forward<Args>(args)...);
return t;
}
template<typename T>
inline void MY_MODULE_DELETE(T* ptr) {
ptr->~T();
// some custom allocator logic here, which deallocates raw memory
// for example purpose just use free
free(ptr);
}
int main() {
SomeClass* sc = MY_MODULE_NEW<SomeClass>();
std::cout << sc->x << std::endl;
SomeClass* sc2 = MY_MODULE_NEW<SomeClass>(*sc);
std::cout << sc2->x << std::endl;
MY_MODULE_DELETE(sc);
MY_MODULE_DELETE(sc2);
}
I have the following concerns:
From the performance point of view, Is this inline function good enough? Can we do better?
Personally I feel MY_MODULE_NEW<SomeClass>(...) syntax is almost similar to the canonical syntax for operator new which is new SomeClass(). Is there any other idiomatic way to achieve the same result?
Thank You!
Related
I wrote a simple template class, which works fine, if the objects are created without using pointers. However if I need to create a pointer to that class object, I get error: invalid conversion from ‘int’ to ‘Logger<int>*’ [-fpermissive]. I am attaching the code below. Any help is appreciated.
Thank you.
#include <iostream>
using namespace std;
template<typename T>
class Logger
{
public:
Logger (const T& d) {data = d;}
void print(){std::cout << "data: " << data << std::endl;}
private:
int data;
};
int main() {
/*
// Works
Logger<int> myLogger(5);
myLogger.print();
*/
Logger<int>* myLogger(5);
myLogger->print();
return 0;
}
If you wanted to allocate a pointer you'd need to use new (and remember to delete it when it is no longer needed so you don't leak it).
Logger<int>* myLogger = new Logger<int>(5);
I don't know what your use case is for doing this, but if you really need to dynamically allocate the object, I'd recommend using smart pointers if you can.
std::unique_ptr<Logger<int>> myLogger = std::make_unique<Logger<int>>(5);
simple multi-inheritance
struct A {};
struct B {};
struct C : A, B {};
or virtual inheritance
struct B {};
struct C : virtual B {};
Please note types are not polymorphic.
Custom memory allocation:
template <typedef T, typename... Args>
T* custom_new(Args&& args...)
{
void* ptr = custom_malloc(sizeof(T));
return new(ptr) T(std::forward<Args>(args)...);
}
template <typedef T>
void custom_delete(T* obj)
{
if (!obj)
return obj;
void* ptr = get_allocated_ptr(obj); // here
assert(std::is_polymorphic_v<T> || ptr == obj);
obj->~T();
custom_free(ptr); // heap corruption if assert ^^ failed
}
B* b = custom_new<C>(); // b != address of allocated memory
custom_delete(b); // UB
How can I implement get_allocated_ptr for non polymorphic types? For polymorphic types dynamic_cast<void*> does the job.
Alternatively I could check that obj is a pointer to a base class as deleting a non polymorphic object by a pointer to base class is UB. I don't know how to do this or if it's possible at all.
operator delete properly deallocates memory in such cases (e.g. VC++), though standard says it's UB. How does it do this? compiler-specific feature?
You actually have a more serious problem than getting the address of the full object. Consider this example:
struct Base
{
std::string a;
};
struct Derived : Base
{
std::string b;
};
Base* p = custom_new<Derived>();
custom_delete(p);
In this example, custom_delete will actually free the correct address (static_cast<void*>(static_cast<Derived*>(p)) == static_cast<void*>(p)), but the line obj->~T() will invoke the destructor for Base, meaning that the b field is leaked.
So Don't Do That
Instead of returning a raw pointer from custom_new, return an object that is bound to the type T and that knows how to delete it. For example:
template <class T> struct CustomDeleter
{
void operator()(T* object) const
{
object->~T();
custom_free(object);
}
};
template <typename T> using CustomPtr = std::unique_ptr<T, CustomDeleter<T>>;
template <typename T, typename... Args> CustomPtr<T> custom_new(Args&&... args)
{
void* ptr = custom_malloc(sizeof(T));
try
{
return CustomPtr<T>{ new(ptr) T(std::forward<Args>(args)...) };
}
catch (...)
{
custom_free(ptr);
throw;
}
}
Now it's impossible to accidentally free the wrong address and call the wrong destructor because the only code that calls custom_free knows the complete type of the thing that it's deleting.
Note: Beware of the unique_ptr::reset(pointer) method. This method is extremely dangerous when using a custom deleter since the onus is on the caller to supply a pointer that was allocated in the correct way. The compiler can't help if the method is called with an invalid pointer.
Passing Around Base Pointers
It may be that you want to both pass a base pointer to a function and give that function responsibility for freeing the object. In this case, you need to use type erasure to hide the type of the object from consumers while retaining knowledge of its most derived type internally. The easiest way to do that is with a std::shared_ptr. For example:
struct Base
{
int a;
};
struct Derived : Base
{
int b;
};
CustomPtr<Derived> unique_derived = custom_new<Derived>();
std::shared_ptr<Base> shared_base = std::shared_ptr<Derived>{ std::move(unique_derived) };
Now you can freely pass around shared_base and when the final reference is released, the complete Derived object will be destroyed and its correct address passed to custom_free. If you don't like the semantics of shared_ptr, it's fairly straightforward to create a type erasing pointer with unique_ptr semantics.
Note: One downside to this approach is that the shared_ptr requires a separate allocation for its control block (which won't use custom_malloc). With a little more work, you can get around that. You'd need to create a custom allocator that wraps custom_malloc and custom_free and then use std::allocate_shared to create your objects.
Complete Working Example
#include <memory>
#include <iostream>
void* custom_malloc(size_t size)
{
void* mem = ::operator new(size);
std::cout << "allocated object at " << mem << std::endl;
return mem;
}
void custom_free(void* mem)
{
std::cout << "freeing memory at " << mem << std::endl;
::operator delete(mem);
}
template <class T> struct CustomDeleter
{
void operator()(T* object) const
{
object->~T();
custom_free(object);
}
};
template <typename T> using CustomPtr = std::unique_ptr<T, CustomDeleter<T>>;
template <typename T, typename... Args> CustomPtr<T> custom_new(Args&&... args)
{
void* ptr = custom_malloc(sizeof(T));
try
{
return CustomPtr<T>{ new(ptr) T(std::forward<Args>(args)...) };
}
catch (...)
{
custom_free(ptr);
throw;
}
}
struct Base
{
int a;
~Base()
{
std::cout << "destroying Base" << std::endl;
}
};
struct Derived : Base
{
int b;
~Derived()
{
std::cout << "detroying Derived" << std::endl;
}
};
int main()
{
// Since custom_new has returned a unique_ptr with a deleter bound to the
// type Derived, we cannot accidentally free the wrong thing.
CustomPtr<Derived> unique_derived = custom_new<Derived>();
// If we want to get a pointer to the base class while retaining the ability
// to correctly delete the object, we can use type erasure. std::shared_ptr
// will do the trick, but it's easy enough to write a similar class without
// the sharing semantics.
std::shared_ptr<Base> shared_base = std::shared_ptr<Derived>{ std::move(unique_derived) };
// Notice that when we release the shared_base pointer, we destroy the complete
// object.
shared_base.reset();
}
You can do that only using dynamic_cast and static type of T has to be polymorphic. Otherwise look at this code:
struct A { int a; };
struct B { int b; };
struct C : A, B {};
B *b1 = new C, *b2 = new B;
If you try to delete by pointer to B, there is no way to know if b1 or b2 needs to be adjusted to get_allocated_ptr. One way or another you need B to be polymorphic to get pointer to most derived object.
What about a virtual interface that all structs inherit from, which returns the pointer at which the object was allocated? I had to make some changes to make the code compile. Both the multiple inheritance and virtual inheritance cases work:
#include <iostream>
#include <type_traits>
#include <cassert>
struct H {
public:
void* getHeader() { return header; }
void setHeader(void* ptr) { header = ptr; }
private:
void* header;
};
// multiple inheritance case
//struct A : public virtual H { int a;};
//struct B : public virtual H { int b;};
//struct C : A, B { };
// virtual inheritance case
struct B : public virtual H { int b; };
struct C : virtual B {};
template <typename T, typename ...Args>
T* custom_new(Args&&... args) {
void* ptr = malloc(sizeof(T));
T* obj = new(ptr) T(std::forward<Args>(args)...);
obj->setHeader(ptr);
return obj;
}
template <typename T>
void* get_allocated_ptr(T* obj) {
return obj->getHeader();
}
template <typename T>
void custom_delete(T* obj) {
void* ptr = get_allocated_ptr(obj); // here
// assert(std::is_polymorphic<T>::value || ptr == obj); // had to comment
obj->~T();
free(ptr); // heap corruption if assert ^^ failed
}
using namespace std;
int main(int argc, char *argv[]) {
C* c = custom_new<C>(); // b != address of allocated memory
std::cout << "PTR \t\t= " << c << std::endl;
auto b = static_cast<B*>(c);
std::cout << "CAST PTR \t= " << b << std::endl;
std::cout << "ALLOCATED PTR \t= " << get_allocated_ptr(b) << std::endl;
custom_delete(b); // UB
}
You can run this with either hierarchy, and the output is something like
PTR = 0x7f9fd4d00b90
CAST PTR = 0x7f9fd4d00b98
ALLOCATED PTR = 0x7f9fd4d00b90
although in the multiple inheritance case the pointers differ by 16 bits rather than 8 (because of the two integers).
This implementation could be improved by using templates to enable custom_new and the other functions only for structs inheriting from the H interface.
I'm writing python wrapper for my project which uses Eigen for it's mathematical computations. After testing basic operations, eigen objects created inside python always return incorrect results. This usually happened to me when I didn't respect data alignments using Eigen. This is solved by allocating eigen objects using Eigen::aligned_allocator. How can I tell boost to allocate eigen objects using Eigen::aligned_allocator ?
Here's a simple test:
C++
using namespace boost::python;
using namespace Eigen;
class_<Isometry3d>("Isometry3d", init<>())
.def("__str__", make_function(IsometryToStr))
.def_readonly("Identity", Isometry3d::Identity())
;
IsometryToStr function simply uses operator << which is defined by the Eigen.
Python:
a = Isometry3d.Identity
print a
We would expect it to print the identity matrix, but the result is always different.
To control the allocation of C++ types, register a factory function as the Python object's constructor with make_constructor. Often times, custom allocation also implies custom deallocation, in which case boost::shared_ptr can be used to manage the lifetime of the object and invoke a custom dealloction strategy. This answer goes into more details, but here is a complete example with a basic custom allocator.
#include <cstdlib>
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
/// #brief Basic custom allocator.
template <typename T>
class custom_allocator
{
public:
typedef size_t size_type;
typedef T* pointer;
typedef T value_type;
public:
pointer allocate(size_type num, const void* hint = 0)
{
std::cout << "custom_allocator::allocate()" << std::endl;
return reinterpret_cast<pointer>(
std::malloc(num * sizeof(value_type)));
}
void deallocate(pointer p, size_type num)
{
std::cout << "custom_allocator::deallocate()" << std::endl;
std::free(p);
}
};
/// #brief Example class.
class foo
{
public:
foo() { std::cout << "foo()" << std::endl; }
~foo() { std::cout << "~foo()" << std::endl; }
void action() { std::cout << "foo::action()" << std::endl; }
};
/// #brief Allocator for foo.
custom_allocator<foo> foo_allocator;
/// #brief Destroy a foo object.
void destroy_foo(foo* p)
{
p->~foo(); // Destruct.
foo_allocator.deallocate(p, 1); // Deallocate.
}
/// #brief Factory function to create a foo object.
boost::shared_ptr<foo> create_foo()
{
void* memory = foo_allocator.allocate(1); // Allocate.
return boost::shared_ptr<foo>(
new (memory) foo(), // Construct in allocated memory.
&destroy_foo); // Use custom deleter.
}
BOOST_PYTHON_MODULE(example) {
namespace python = boost::python;
// Expose foo, that will be managed by shared_ptr, and transparently
// constructs the foo via a factory function to allow for a custom
// deleter to use the custom allocator.
python::class_<foo, boost::shared_ptr<foo>,
boost::noncopyable>("Foo", python::no_init)
.def("__init__", python::make_constructor(&create_foo))
.def("action", &foo::action)
;
}
And the usage:
>>> import example
>>> f = example.Foo()
custom_allocator::allocate()
foo()
>>> f.action()
foo::action()
>>> f = None
~foo()
custom_allocator::deallocate()
We want to work on low latency system, heap allocation is costlier in the application. but for some extent object creation on heap is allowed. Thats why we want indication whether object is created is on heap or not..?
Is the below methodology is the correct way to find out object created on heap memory..?
Will have generic class where new and delete operator is overloaded to maintain heap allocated pointers....
#include <iostream>
#include <set>
using namespace std;
class MemStat //base class
{
typedef set<MemStat*> POINTERS;
static POINTERS m_ptrlist;
public:
void* operator new (size_t size)
{
MemStat* ptr = ::new MemStat;
m_ptrlist.insert(ptr);
return ptr;
}
void operator delete(void* dptr)
{
MemStat* ptr = static_cast<MemStat*>(dptr);
m_ptrlist.erase(ptr);
::delete ptr;
}
// void* operator new[] (size_t sz);
// void operator delete[] (void*);
bool is_on_heap() { m_ptrlist.find(this) != m_ptrlist.end(); }
protected: // ctor & dtor are protected for restrictions
MemStat() { }
virtual ~MemStat() { }
MemStat(const MemStat&) { }
const MemStat& operator=(const MemStat& ) { return *this; }
};
MemStat::POINTERS MemStat::m_ptrlist;
for the end user classes which we need to check for the heap creation will be derived from MemStat class uses new & delete operator call while instantiating base class object.
class MyClass : public MemStat //end user class
{
};
int main()
{
MyClass* myptr = new MyClass;
MyClass obj;
cout << myptr->is_on_heap() << endl; //results into yes
cout << obj.is_on_heap() << endl; //reults into no
delete myptr;
}
Note that your scheme fails miserably as soon as a MyClass object is a sub-object (inherited or contained) of another object which might or might not by allocated dynamically. (And the tricks I know for preventing dynamic allocation fail on that one as well.)
So what you're doing just further slows down heap allocation without gaining much. Except for a few very rare circumstances, where an object is allocated is something your class' users decide.
If they think they need to dynamically allocate one, who are you to disagree?
I have a function where I want a cleanup action done 90% of the time, but in 10% I want some other action to be done.
Is there some way to use some standard scoped control likeshared_ptr<> so that initially it can have one delete action and then later in the function the delete action can be changed?
shared_ptr<T> ptr( new T, std::mem_fun_ref(&T::deleteMe) );
ptr.pn.d = std::mem_fun_ref(&T::queueMe);
Not really - the standard for shared_ptr is written in such a way that the Deleter may be stored by value in control node (a special object that contains the reference counter, holds deleter, tracks weak pointers etc). The deleter is type-erased, but if you know the concrete deleter type somehow, you can use std::get_deleter<Deleter>(ptr). With it you may access the deleter and change its state. Example:
struct A {};
struct deleter {
void operator()(A* a) {delete a; }
int m_state;
};
std::shared_ptr<A> ptr(new A(), deleter{});
std::get_deleter<deleter>(ptr)->m_state = 5;
And if you use just a function pointer for all deleters, then yes you can completely replace it, as all potential deleters use the same signature.
(Yes I know the question is 9 years old, but I've just faced this problem in 2020 and solved it like this. The possible reason for it is wrapping C pointers and objects from legacy code that manage ownership through raw pointers)
I don't think you can change the deleter once the shared_ptr was created.
But why would you do that ? Usually, when you create an object, you know immediatly how it must be destroyed. This is not likely to change.
If you really must do some specific treatments, you still can provide a custom deleter which does special things depending on the required logic.
There is a valid reason to need to change the deleter. Take this for example:
int foo( std::shared_ptr<double>& bar ) {
...
std::shared_ptr<double> p( my_allocator<double>::allocate(), my_deleter<double>() );
bar.swap(p); // this copies the deleter
...
}
int main( int, char** ) {
std::shared_ptr<double> d;
foo( d ); // d now has a new deleter that will be called when it goes out of scope
...
}
In this case the foo() function allocates a double* using some special allocator. It needs to free that memory in a special way also. The caller shouldn't need to know how to free the memory.
#include <iostream>
#include <memory>
#include <functional>
struct A {
~A() {
std::cout << "~A()" << std::endl;
}
};
using DeleterCb = std::function<void(A* p)>;
struct ADeleter {
public:
explicit ADeleter(DeleterCb cb) :
mDeleterCb(cb) {}
ADeleter() = delete;
~ADeleter() = default;
void operator()(A *a) {
mDeleterCb(a);
}
void setDeleterCb(DeleterCb cb) {
mDeleterCb = cb;
}
private:
DeleterCb mDeleterCb;
};
int main() {
auto sp = std::shared_ptr<A>(new A{},
ADeleter([](A *p){
delete p;
std::cout << "deleter_1" << std::endl;
})
);
std::get_deleter<ADeleter>(sp)->setDeleterCb(
[](A *p){
delete p;
std::cout << "deleter_2" << std::endl;
}
);
}
This doesn't make any sense, since there is any number of shared_ptrs managing the ownership of the value. You'd need to modify them all, and that's not feasible. Let's not forget that a control block is an implementation detail, so going "aha, but change it in the control block" won't work.
The delete actions should be controlled by the instance owned by shared_ptr, e.g.
class C {
...
void (C::action*)() { &C::action1 };
void action1();
void action2();
~C() { (this->*action)(); }
};
void test() {
std::shared_ptr<C> a;
a->action = &C::action2;
// action2 gets invoked once `a` falls out of scope
}