Safe way of casting void* to something higher? - c++

I've got a generic class that manages resources of all kinds of types, but since I don't want to create an instance of ResourceManager for every T there is (thus having one resource manager for each type T), I have to make the type of T unknown to the ResourceManager class.
I do this by saving a map of void* pointers and converting them back to the required format if someone requests a certain type out of a templated Load() method;
template <typename T>
T* Load(const std::string &location)
{
//do some stuff here
//everybody take cover!!!
return static_cast<T*>(m_resources[location]);
}
I use template specialization to introduce different Loaders to the class:
template<>
AwesomeType* Load(const std::string &location)
{
//etc.
return static_cast<AwesomeType*>(m_resources[location]);
}
I am aware that this is ugly, but there is no way around it right now. I could introduce static maps in the inside of the specialized Load methods, but that way I can't bind the lifetime of the resources to the lifetime of an ResourceManager object, which is an essential feature.
But since this is somewhat dangerous (since those void* pointers can be anything), I'd like to at least check at runtime if the conversion is going to work, so I can react to it without having the application crash.
How can I do this?

There is no way to check what you can cast void* to, unless you store additional information that indicates the actual type with each pointer.
A more "C++ way" to do what you want is to derive each resource class from an abstract base class Resource, and store a map of pointers to Resource in your resource manager. Then you can use dynamic_cast<T*> to convert to the required type, and this will return NULL if the pointer is to an object of the wrong type. Or (depending on what you want to do) you can simply return a Resource* pointer and use virtual functions to implement the functionality of each resource.

You can easily do this, if you extend your saved value type - make it a struct that also saves a type_info object:
#include <type_info>
struct ResourceInfo
{
std::type_info const& info;
void* ptr;
};
// ...
// just to give you the general idea
template<class Res>
void CacheResource(std::string const& location, Res* res)
{
ResourceInfo ri = { typeid(Res), res };
m_resources.insert(std::make_pair(location, ri));
}
template<class Res>
Res* Load(std::string const& location)
{
map_type::const_iterator res_it = m_resources.find(location);
if(res_it != m_resources.end())
{
if(typeid(Res) != res_it->second.info)
{
throw SorryBuddyWrongResourceType(some_info_here);
}
return static_cast<Res*>(res_it->second.ptr);
}
}
This is similar to how I do it, but I use a shared_ptr<void> to save the resources.

(I'm sure this is already answered by many other questions about void pointers, but here we go ...)
But since this is somewhat dangerous
(since those void* pointers can be
anything), I'd like to at least check
at runtime if the conversion is going
to work, so I can react to it without
having the application crash.
You cannot check. This is the thing about void* pointers. You don't have a clue what they are pointing to, and you cannot (are not allowed to) inspect the memory they point to without knowing its type.
If you have a void* you simply must know beforehand what it is really pointing to and then cast appropriately.

Related

Determine the type of a pointer

So I am making a Memory Stack Allocator that is capable of allocating any instance of any type onto the heap in a continuous fashion.
In order to do this i have added a 'AllocationHeader' class directly before each allocation which contains a void* to the instance address itself and a AllocationHeader* to the previous header.
So far this has worked perfectly and i'm able to allocate and deallocate etc.
But i've ran into 1 (possibly 2) problems.
In order to deallocate properly I also need to call the destructor of the object in question and then remove it from the stack.
This is fine when i'm removing an instance that i have a pointer to as i can just pass it to the deallocate function and it knows what type it is and does its thing.
The problem lies when I want to create functions like deallocateAll() or deallocateAllAboveObject(T* obj) as I would need to know the types of each allocation without explicitly passing their pointer, so i could go down each allocation in the stack calling the deconstructor on each as I go.
What I would like is to be able to create an AllocationHeader which can store a pointer of any type, and then the type of the pointer can be retrieved at a later date without already knowing the type.
I'm really not sure how to do this as all suggestions that i've seen so far involve comparing the object with a specific type and seeing if they're the same. However I can't just check against each possible class in the program as there could be 1000's as I continue to build on this.
Alternatively if you have any suggestions for an alternative approach to a stack allocator that can deal with any type, that would be great as well.
Any help at all would be greatly appreciated.
Due to C++'s static type system, I can only see a couple of solutions to the problem
Make every type you use with the allocator derive from a (consistent) type with a virtual distructor e.g. struct destructible { virtual ~destructible() { } }, however this will potentially enlarge & alter the layout of any types you alter to derive from this.
Or uppon allocation store a function object that does the destruction, e.g. using the following template
template<typename T> void destroy(void* p) { reinterpret_cast<T*>(p)->T::~T(); }
struct AllocationHeader
{
template<typename T> AllocationHeader(AllocationHeader* previouse, void* data)
: previouse(previouse), data(data), destructor(&destroy<T>) { }
AllocationHeader* previouse;
void* data;
void (*destructor)(void*);
}
void deallocateAll(AllocationHeader& start)
{
for (AllocationHeader* a = &start; a != nullptr; a = start->previouse;)
{
a->destructor(a->data);
delete a->data;
}
}
(Without providing your code for the AllocationHeader type it is difficuilt to help you.)
Note: My compiler/IDE is currently reinstalling so I am unable to test the above code, I am pretty sure about most of it, except I may need to put a typename in the destructor call syntax reinterpret_cast<T*>(p).T::~T();
EDIT Using a template constructor, where the template arguments cannot be inferred is a bad idea, the following constructor should be used instead
AllocationHeader(AllocationHeader* previouse, void* data, void(*destructor)(void*))
: previouse(previouse), data(data), destructor(destructor) { }
Just pass &destroy<T> as the 3rd argument to it.

Shared Ownership double free error

I have an Engine class which contains and owns some Systems. The Engine class has two containers, one map and one vector. Both keep pointers to the Systems.
The addSystem template function should add a pointer of a new System of the wanted type in the map and the addToPipeline should add a pointer of the System passed as a parameter in the vector. I used shared_ptrs for this but I am doing something wrong because I get a double free error if I use the addToPipeline function.
Here is the simplified Engine class:
class Engine
{
public:
template <class T>
T& addSystem();
void addToPipeline(System&);
private:
std::map<std::type_index, std::shared_ptr<System>> m_systems;
std::vector<std::shared_ptr<System>> m_pipeline;
};
void Engine::addToPipeline(System& sys)
{
m_pipeline.push_back(std::shared_ptr<System>(&sys));
}
template <class T>
T& Engine::addSystem()
{
std::shared_ptr<T> system = std::make_shared<T>();
auto inserted = m_systems.emplace(typeid(T),system);
return static_cast<T&>(*(*inserted.first).second);
}
The functions should be used like shown below:
auto& POSITION_SYSTEM = engine.addSystem<PositionSystem>();
engine.addToPipeline(POSITION_SYSTEM);
Any help is appreciated!
In this line:
m_pipeline.push_back(std::shared_ptr<System>(&sys));
You are creating a shared_ptr for an already managed object, since you already wrapped the same object in another smart pointer. So you end up with two reference counts for the same object, thus you get a double free.
This is not how shared_ptr should be used. Instead, you should return a shared_ptr from addSystem and take one as argument for addToPipeline:
void Engine::addToPipeline(std::shared_ptr<System> sys)
{
m_pipeline.push_back(sys);
}
template <class T>
std::shared_ptr<T> Engine::addSystem()
{
std::shared_ptr<T> system = std::make_shared<T>();
m_systems.emplace(typeid(T),system);
return system; // No need to use the return value of emplace
}
The idea with shared_ptrs is that instead of using bare pointers or references, you always pass a shared_ptr (unless ownership doesn't matter - then you can also pass a reference). You have to do it this way because the reference counter is managed by the smart pointers.
Edit: As rozina pointed out: Of course you can still pass references to the managed object, as long as nobody tries to delete the corresponding address. This might actually be preferable if other code is interested in using a certain object, but not concerned about ownership. For example, you might want to have a public interface which allows obtaining a reference to some object that's managed by a smart pointer internally. For example:
class Foo {
public:
Bar& getBar() {
return *m_bar;
}
private:
std::shared_ptr<Bar> m_bar;
};
This is perfectly fine as long as nobody does delete &aFoo.getBar() - which happens if you create a new shared_ptr with that reference, as you did in your original code.

C++11 shared_pointer constness within stl containers

I have the following problem and I wonder whether there's a better way to solve it:
class myObj {
public:
typedef std::shared_ptr<myObj> handle;
typedef std::shared_ptr<const myObj> const_handle;
int someMethod() { ... }
int someConstMethod() const { ... }
};
Now what I need is a container class that somehow allows you to modify or read a collection of myObj depending on its own constness, like so:
class myCollection {
public:
typedef std::list<myObj::handle> objList;
typedef std::list<myObj::const_handle> const_objList;
inline objList& modify() { return _obl; }
// it would be nice to do this, but it won't compile as
// objList and const_objList are completely different types
inline const_objList& read() const { return _obl; } // doh! compile error...
// returning a const objList won't help either as it would return non-const
// handles, obviously.
// so I am forced to do this, which sucks as i have to create a new list and copy
void read(const_objList &l) {
std::for_each(
_obl.begin(),
_obl.end(),
[&l] (myObj::handle &h) { l.push_back(h); }
// ok as handle can be cast to const_handle
); // for_each
}
private:
objList _obl;
};
So this solution actually works as a const myCollection would only allow you to get a list of const_handle which only allows you to call non-modifying methods of myObj (GOOD).
The problem is that the "read" method is really ugly (BAD).
Another method would be to expose somehow the list methods and return const_handle and handle as needed but it's a lot of overhead, especially if you want to use something more complex than a list.
Any idea?
A list-of-pointers-to-T is not a list-of-pointers-to-constant-T.
std::list<std::shared_ptr<int>> a;
std::list<std::shared_ptr<const int>>& ra = a; // illegal but imagine it's not
std::shared_ptr<const int> x = std::make_shared<const int>(42);
ra.push_back(x); // totally legal, right?
++**a.begin(); // oops... just incremented a const int
Now a list-of-pointers-to-T is, conceptually, a constant-list-of-constant-pointers-to-constant-T, but std::list<std::shared_ptr<T>> does not support such a deep const propagation. const std::list<std::shared_ptr<T>> contains constant pointers to non-constant objects.
You can write your own variant of list<> or your own variant of shared_ptr<> that have such support. It probably won't be very easy though. A const_propagating_shared_ptr is probably the easier of the two. It would have to encapsulate an std::shared_ptr<T> object and forward almost everything to it as-is. As opposed to std::shared_ptr<T> it would have separate const and non-const versions of operator->, operator*() and get().
Given what you stated that you want to accomplish, I don't think that your solution is too bad. Imagine that some other code may be modifying the internal collection, like adding or removing values. Returning a copy of the current state of the collection is safe for client code, since it can work on the copy, without the danger of element being deleted in the meantime. But I digress, this is getting into threading issues and may not be relevant.
You could use prettier:
inline const_objList read() const
{
const_objList cl(_obl.begin(), _obl.end());
return cl;
}
However, I do think that your problems derive from mixing two types of constness: constness of the members of the collection versus the constness of the collection itself.
Instead of Modify and Read methods, that deal with the list as a whole, I would try exposing const and non-const iterators to internal list, through corresponding const and non-const methods returning said iterators.
But this immediately begs the question: why then have myCollection in the first place?
Creating entirely new collection type around std::list doesn't seem needed, unless you get a lot of proverbial bang for the buck from other, added functionality that is not visible in your sample.
You can then make your added functionality free methods that take std::list of your handles as the input. Not everything requires an object and operations on objects need not necessarily be member methods, unless access to private data is required.
You mentioned maybe using another container instead of the list. But your class, as is, won't do it, unless you have a template, where template parameter can be one of STL containers.
Which then implies that you should expose iterators.
Namely, if you foresee changing the internal collection type, you would want to make the public interface to myCollection transparent regarding the collection type. Otherwise, clients will have to recompile each time you change your mind about the internal implementation.
EDIT -----
Finally, if implementing iterators (while interesting and most correct) is too much, why not go for simple getters like in this SO post:
smart pointer const correctness
I'll quote the topmost answer by Rüdiger Stevens (it assumes vector instead of list):
template <typename T>
class MyExample
{
private:
vector<shared_ptr<T> > data;
public:
shared_ptr<const T> get(int idx) const
{
return data[idx];
}
shared_ptr<T> get(int idx)
{
return data[idx];
}
void add(shared_ptr<T> value)
{
data.push_back(value);
}
};

How to store different data types in one list? (C++)

I need to store a list of various properties of an object. Property consists of a name and data, which can be of any datatype.
I know I can make a class "Property", and extend it with different PropertySubClasses which only differ with the datatype they are storing, but it does not feel right.
class Property
{
Property(std::string name);
virtual ~Property();
std::string m_name;
};
class PropertyBoolean : Property
{
PropertyBoolean(std::string name, bool data);
bool m_data;
};
class PropertyFloat : Property
{
PropertyFloat(std::string name, float data);
float m_data;
};
class PropertyVector : Property
{
PropertyVector(std::string name, std::vector<float> data);
std::vector<float> m_data;
};
Now I can store all kinds of properties in a
std::vector<Property*>
and to get the data, I can cast the object to the subclass. Or I can make a pure virtual function to do something with the data inside the function without the need of casting.
Anyways, this does not feel right to create these different kind of subclasses which only differ by the data type they are storing. Is there any other convenient way to achieve similar behavior?
I do not have access to Boost.
C++ is a multi-paradigm language. It shines brightest and is most powerful where paradigms are mixed.
class Property
{
public:
Property(const std::string& name) //note: we don't lightly copy strings in C++
: m_name(name) {}
virtual ~Property() {}
private:
std::string m_name;
};
template< typename T >
class TypedProperty : public Property
{
public:
TypedProperty (const std::string& name, const T& data)
: Property(name), m_data(data);
private:
T m_data;
};
typedef std::vector< std::shared_ptr<Property> > property_list_type;
Edit: Why using std::shared_ptr<Property> instead of Property*?
Consider this code:
void f()
{
std::vector<Property*> my_property_list;
for(unsigned int u=0; u<10; ++u)
my_property_list.push_back(new Property(u));
use_property_list(my_property_list);
for(std::vector<Property*>::iterator it=my_property_list.begin();
it!=my_property_list.end(); ++it)
delete *it;
}
That for loop there attempts to cleanup, deleting all the properties in the vector, just before it goes out of scope and takes all the pointers with it.
Now, while this might seem fine for a novice, if you're an only mildly experienced C++ developer, that code should raise alarm bells as soon as you look at it.
The problem is that the call to use_property_list() might throw an exception. If so, the function f() will be left right away. In order to properly cleanup, the destructors for all automatic objects created in f() will be called. That is, my_property_list will be properly destroyed. std::vector's destructor will then nicely cleanup the data it holds. However, it holds pointers, and how should std::vector know whether these pointers are the last ones referencing their objects?
Since it doesn't know, it won't delete the objects, it will only destroy the pointers when it destroys its content, leaving you with objects on the heap that you don't have any pointers to anymore. This is what's called a "leak".
In order to avoid that, you would need to catch all exceptions, clean up the properties, and the rethrow the exception. But then, ten years from now, someone has to add a new feature to the 10MLoC application this has grown to, and, being in a hurry, adds code which leaves that function prematurely when some condition holds. The code is tested and it works and doesn't crash - only the server it's part of now leaks a few bytes an hour, making it crash due to being out of memory about once a week. Finding that makes for many hours of fine debugging.
Bottom line: Never manage resources manually, always wrap them in objects of a class designed to handle exactly one instance of such a resource. For dynamically allocated objects, those handles are called "smart pointer", and the most used one is shared_ptr.
A lower-level way is to use a union
class Property
union {
int int_data;
bool bool_data;
std::cstring* string_data;
};
enum { INT_PROP, BOOL_PROP, STRING_PROP } data_type;
// ... more smarts ...
};
Dunno why your other solution doesn't feel right, so I don't know if this way would feel better to you.
EDIT: Some more code to give an example of usage.
Property car = collection_of_properties.head();
if (car.data_type == Property::INT_PROP) {
printf("The integer property is %d\n", car.int_data);
} // etc.
I'd probably put that sort of logic into a method of the class where possible. You'd also have members such as this constructor to keep the data and type field in sync:
Property::Property(bool value) {
bool_data = value;
data_type = BOOL_PROP;
}
I suggest boost::variant or boost::any. [Related question]
Write a template class Property<T> that derives from Property with a data member of type T
Another possible solution is to write a intermediate class managing the pointers to Property classes:
class Bla {
private:
Property* mp
public:
explicit Bla(Property* p) : mp(p) { }
~Bla() { delete p; }
// The standard copy constructor
// and assignment operator
// aren't sufficient in this case:
// They would only copy the
// pointer mp (shallow copy)
Bla(const Bla* b) : mp(b.mp->clone()) { }
Bla& operator = (Bla b) { // copy'n'swap trick
swap(b);
return *this;
}
void swap(Bla& b) {
using std::swap; // #include <algorithm>
swap(mp, b.mp);
}
Property* operator -> () const {
return mp;
}
Property& operator * () const {
return *mp;
}
};
You have to add a virtual clone method to your classes returning a pointer to a newly created copy of itself:
class StringProperty : public Property {
// ...
public:
// ...
virtual Property* clone() { return new StringProperty(*this); }
// ...
};
Then you'll be able to do this:
std::vector<Bla> v;
v.push_back(Bla(new StringProperty("Name", "Jon Doe")));
// ...
std::vector<Bla>::const_iterator i = v.begin();
(*i)->some_virtual_method();
Leaving the scope of v means that all Blas will be destroyed freeing automatically the pointers they're holding. Due to its overloaded dereferencing and indirection operator the class Bla behaves like an ordinary pointer. In the last line *i returns a reference to a Bla object and using -> means the same as if it was a pointer to a Property object.
A possible drawback of this approach is that you always get a heap operation (a new and a delete) if the intermediate objects must be copied around. This happens for example if you exceed the vector's capacity and all intermediate objects must be copied to a new piece of memory.
In the new standard (i.e. c++0x) you'll be able to use the unique_ptr template: It
can be used inside the standard containers (in contrast to the auto_ptr which must not be used in the standard containers),
offers the usually faster move semantics (it can easily passed around) and
takes care over the held pointers (it frees them automatically).
I see that there are lots of shots at trying to solve your problem by now, but I have a feeling that you're looking in the wrong end - why do you actually want to do this in the first place? Is there some interesting functionality in the base class that you have omitted to specify?
The fact that you'd be forced to switch on a property type id to do what you want with a specific instance is a code smell, especially when the subclasses have absolutely nothing in common via the base class other than a name (which is the type id in this case).
Starting with C++ 17 we have something called as std::variant and std::any.
std::variant
An instance of std::variant at any given time either holds a value of one of its alternative types, or in the case of error - no value.
std::any
The class any describes a type-safe container for single values of any copy constructible type.
An object of class any stores an instance of any type that satisfies the constructor requirements or is empty, and this is referred to as the state of the class any object. The stored instance is called the contained object. Two states are equivalent if they are either both empty or if both are not empty and if the contained objects are equivalent.
The non-member any_cast functions provide type-safe access to the contained object.
You can probably do this with the Boost library, or you could create a class with a type code and a void pointer to the data, but it would mean giving up some of the type safety of C++. In other words, if you have a property "foo", whose value is an integer, and give it a string value instead, the compiler will not find the error for you.
I would recommend revisiting your design, and re-evaluating whether or not you really need so much flexibility. Do you really need to be able to handle properties of any type? If you can narrow it down to just a few types, you may be able to come up with a solution using inheritance or templates, without having to "fight the language".

Casting from any

I'm packing some classes into ptr_map with any typed value.
class EventManager
{
ptr_map<string, any> mSomeMap;
public:
typedef signals2::signal<void (int someSignature)> KeyEvent;
EventManager()
{
mSomeMap["KeyPressed"] = new any(new KeyEvent());
}
};
Now I want to restore my signal object from any. Here is a special function for this:
template<typename EventType>
EventType *get(const string &signalName)
{
try {
return any_cast<EventType*>(mSomeMap[signalName]);
} catch(bad_any_cast &e){}
}
As you could remember, the boost's signals are noncopyable so I can store only pointers and my function should return pointers too.
Now sample usage:
evManager.get<EventManager::KeyEvent>("KeyPressed");
Here I get segfault. I checked the types of each objects in the get function:
typeid(EventType).name()
→ N5boost8signals26signalIFvRN2sf5Event8KeyEventEENS0_19optional_last_valueIvEEiSt4lessIiENS_8functionIS6_EENSB_IFvRKNS0_10connectionES5_EEENS0_5mutexEEE
mSignalAssociation[signalName].type().name()
→ N10__cxxabiv119__pointer_type_infoE
What's wrong is there? The segfault at line with casting. Any object should consist of inserted type or not? Why it doesn't want to cast.
ptr_map<string, any> mSomeMap;
...
mSomeMap["KeyPressed"] = new any(new KeyEvent());
Do you realize what happens here? First, you create a KeyEvent object dynamically which results in a pointer. Then this pointer is wrapped into an any-object which is also dynamically created which also returns a pointer which is then again wrapped in another any object implicitly by the assignment.
Also, for extracting the right value from an any object you need to know the exact type. So, for example, if you pack a Derived-pointer into an any object, you won't be able to access it via an any_cast<Base*> because Base* and Derived* are different types in terms of the std::type_info objects boost::any uses to keep track of types. boost::any just doesn't know how to convert the packed Derived-pointer to your Base-pointer.
Is there a special reason why you wrap so many things in any-objects including pointers to any-objects? Wouldn't it make sense to use something like a ptr_map<KeyType,BaseType>? You know that if you pack a pointer into an any object that you still need to delete the pointees yourself, right? The any-object is not going to do this for you.