I serialized a C++ object, how to allocate memory for it without knowing what type it is? - c++

I have serialized a C++ object and I wish to allocate space for it, although I can't use the "new" operator, because I do not know the object's class. I tried using malloc(sizeof(object)), although trying to typecast the pointer to the type the serialized object is of, the program shut down. Where is the information about the object class stored?
class object
{
public:
virtual void somefunc();
int someint;
};
class objectchild:public object
{
}
object *o=(object*)malloc(sizeof(objectchild));
cout << int(dynamic_cast<objectchild*>(o)) << endl;
This causes a program shutdown.
Thank you in advance.

I have serialized a C++ object
I'm not sure you have. If you've written anything like this:
object *p = new objectchild();
some_file.write((char*)p, sizeof(objectchild));
then you haven't serialized your object. You've written some data to file, and (in most implementations) that data includes a pointer to a vtable and type information. When you "deserialize" the data, on another machine or in another run of the same program, the vtable will not in general be at the same address, and the pointer is useless.
The only way to serialize an object in C++ is to write its data members, in a known format you design. That known format should include enough information to work out the type of the object. There are frameworks that can help you with this, but unlike Java there is no mechanism built into the language or standard libraries.

you should not mix C++ and C memory routes. dynamic_cast checks actual type of object. in your case you have raw memory casted to object *

Rewrite your code so that you can read the type of the object in some way from your serialized archive. You can do this by string or by some custom values you use, but it probably won't be generic.
For example, if you are writing a CFoo object, first stream the value "1". If you are writing a CBar, stream the value "2 .
Then, when reading back the archive, if you see a "1" you know you have to "new" a CFoo, and if you read a "2" you know you have to new a CBar.
Alternatively, you could use a full-featured serialization library (or use it as inspiration).
See for example boost::serialization

You need the following code
object *o = new objectchild;
to use dynamic_cast.

You're trying to dynamic_cast a memory location with nothing in it. malloc has given you free space to place an object, but until the new() operator is called no object is there, so when dynamic_cast does it's type-safety check it will fail. You could try using static_cast rather than dynamic_cast, since static doesn't do a type-safety check, but really you shouldn't mix C and C++ allocation/casting styles like that.

Related

API return type -- Force a smart pointer onto the user?

Suppose I have an API-border function that creates and returns an object:
<?> createOneObject();
What would be the best way to return the object to the caller?
Return the raw MyObject* and let the caller handle the pointer herself
Return std::shared_ptr<MyObject>
Something else?
Depends.
In general, returning a raw pointer is bad, because the type itself does not communicate ownership. Should the user delete the pointer? If yes, then how? If not, then when does the library do it? How does the user know if the pointer is still valid? Those things have to be documented, and lazy programmers might skip reading the docs. But, if your API must be callable from C or other languages, then a raw pointer may be the only option.
Shared pointer might be useful in special cases, but they do have overhead. If you don't need shared ownership, then use of a shared pointer may be overkill.
Unique pointer is what I would use unless there is specific reason to use something else.
Although, that assumes that a pointer should be returned in the first place. Another great option could be to return an object.
To be a bit more concrete: I have a player class that just stores an id and just offers lots of methods. In this case you would prefer to return by value?
Most definitely.
You have 2 options (without any nasty drawbacks):
C Style
Have a matching void destroyOneObject(MyObject* object); that cleans up the resource. This is the proper choice when destroying the object isn't as simple as deleting it (e.g. needs to be unregistered at some manager class).
Smart pointer
When all that needs to happen is to delete the object, return a std::unique_ptr<MyObject>. This uses RAII to clean up the object, and fits modern C++ a lot better.
The bad solutions
Don't return a raw pointer and call delete on it. You cannot guarantee that the delete matches the new that was used to create the object. It also doesn't communicate very well if you are supposed to delete it in the first place.
Don't use shared pointers. They are complete overkill in almost any situation, and are usually the result of a lack of understanding of an application's structure.

I can't access members of a child class through functions, how do I?

Okay, so my situation is really complex to a relativity new person to C++ like me. I'm making a game (AGK library) and I have a framework class that is the base class for all of the game's objects to have standard functions like frameEvent and such that are to be overwritten by the child object.
That's all fine and dandy, and I've gotten about 70% through development, but I ran across one vital problem.
To make life easier while processing the game, each object that is a part of the game is just a pointer in a vector of type Framework*. Framework being the base class. I was told that making it a pointer allows me to have child objects of different types as long as they're a pointer as well. So far it's worked out.
Every frame, the global object runs through the vector of all the objects and runs their
frameEvent
frameEndEvent -- Can't be overriden
drawEvent
They're really just functions. So in the enemy's bullet class, I need to check if it collides with oPlayer, so I have a functions in the global class (The global class is passed to the objects in their frame event so they can communicate with other objects.) that grabs a given object.
It searches through all of the objects to find the parameter object -- so if I pass new oPlayer, it will return the real oPlayer pointer in the game.
When the bullet collides with the player, it needs to lower the player's health and then destroy itself. So at the create function for the bullet, it creates a dummy player then locates the real one using the global class function. The code is
//Find the player
oPlayer* tempPlayer = new oPlayer;
playerChecker = ObjGlobal->classToObject(tempPlayer);
tempPlayer->objectDestroy();
That code works, but it needs playerChecker to be type Framework* because that's what classToObject returns. But when I later use that pointer, I can't access the player's members even though that's the player's pointer.
playerChecker->hitPoints--;
hitPoints is exclusive to oPlayer. I think it's called object splicing or slicing, but I thought that's what using pointers fixed.
So I tried to make playerChecker type oPlayer*, but it says that Framework* can't be converted to it. So I have no idea what to do.
Any help is greatly appreciated.
Your Framework* from classToObject can be downcast to a oPlayer* using a dynamic_cast, like so:
oPlayer* playerChecker = dynamic_cast<oPlayer*>(ObjGlobal->classToObject(tempPlayer));
if (oPlayer) {
// cast succeeded, do stuff with the pointer
}
dynamic_cast is a C++ type cast operator just like the C-style cast, with some special properties. It is specifically designed to convert between pointers or references to polymorphic objects (like your oPlayer, which can be treated as both a Framework and an oPlayer). It also adds a run-time check which verifies that the object you're trying to downcast is indeed an instance of the class you're trying to cast to. If it isn't, it will return a null pointer, or in the case of references, throw an exception.
Your code will also work with a C-style cast or a static_cast (which is much like a C-style cast with compile-type type checking).
static_cast<oPlayer*>(ObjGlobal->classToObject(tempPlayer)) // static_cast
(oPlayer*)ObjGlobal->classToObject(tempPlayer) // C-style cast
These have less overhead because of the lack of a run-time check, but that also means that they are unsafe unless you can guarantee that the pointer you're casting points to an object of the correct type. Also, since dynamic_cast has a very specific use, it makes it clear what your intent is.
What's the error you're getting? Please post this, as we can't offer much help otherwise.
If I had to guess, you forgot to add public: to your class FrameWork. This, or you don't have setters/getters in your class.

how to best assign the pointer onto a _vector_ object to a "void *" variable in c++?

I have the scenario where I have two "worlds" of C++ codes separated by a calling barrier that is only C for design reasons. (in more detail: I have a main thread and multiple child threads where each of the childs can service me calling a bunch of functions with a passed set of arguments and returning the functions result. the interconnect is pure C but the architecture is shared memory and the data to pass are for some of the calls C++ vector objects.)
Doing it the simple way on a vector failed for me - this statement only gets the pointer on the data of the object but not the object pointer itself:
vector<something> my_object;
void * argv0 = &my_object;
If I learnt the right way the class is designed for providing me a pointer onto it's data array rather than a pointer on the object (which further has special members for management like size or allocated space). as the target layer is not capable to manage and update the special members it will happen that any need for alterations to that area can not be done. In other words the "operator=" has a class-defined pairing of "(void *) = (vector)" and I don't see how to overcome that in a direct C++ fashion.
My next best guess was this C fashion approach:
typedef union
{
void * pvObject;
vector<something> * pcObject;
} VECTOR_VOID_UNION_T;
vector<something> my_object;
VECTOR_VOID_UNION_T uVV;
uVV.pcObject = &my_object;
void * argv0 = uVV.pvObject;
I am really not sure if this is the best or only way to do it in a case with such sort of class design. There might be other operators like the C++ extended casting operators that might solve the access problem to the object pointer itself much more gently. but as of now any attempt I tried out did not give me success.
My question is now:
How to correctly and more elegantly overcome that class-defined =operator (or one of it's equivalents) in a C++ fashion so that finally the pointer to the vector object [edit: not the vector data] is stored in the variable of type "void*"?
You are probably looking for this:
void *argv0 = reinterpret_cast<void *>(&my_object);
If you're trying to get a void* that points to the vector's data:
assert(!theVector.empty());
void* thePtr = static_cast<void*>(theVector.data());
It's kind of hard to tell what you're asking, though.

P/Invoke: Memory corruption with pointer

I'm wrapping part of the FBX SDK (closed, with a public API) with Mono (so COM, CLI aren't options) and a bunch of extern's, and it was all going well until I had to return a non-pointer instance. See here
The crucial point is that I have to return it back to C++ for another call. Because I don't know how you'd do that without a pointer, I returned it as such:
FBXAPI FbxProperty* Object_GetFirstProperty(FbxObject* obj)
{
return &obj->GetFirstProperty();
}
..and it's not until I try something like the next snippet that I get the "System.AccessViolationException : Attempted to read or write protected memory. This is often an indication that other memory is corrupt." message.
FBXAPI const wchar_t* Property_GetName(FbxProperty* prop)
{
int c = prop->GetSrcPropertyCount();
return L"Test";
}
If I use almost identical code using the same calls in C++, it's fine. I've done another ~20 function calls in the same manner but without having to "pointerfy" it, and they're all fine too, so I don't think my DllImport's are to blame. So if the reference is to be blame, how else do I do it? Surely I don't store a global static reference somewhere just because someone called it from the API?
Any help is appreciated, C/C++ and the explicit way it handles memory is new to me.
I assume your program is crashing because the property you were getting the pointer to does no longer exist. Let me clarify and start by dissecting the following:
FBXAPI FbxProperty* Object_GetFirstProperty(FbxObject* obj)
{
return &obj->GetFirstProperty();
}
I looked up the documentation of FBX, and FbxObject::GetFirstProperty() has a return type of FbxProperty. Notice that the return value isn't any pointer or reference? That means you get a so called 'auto-variable', or in this case a 'temporary'. This kind of object only lasts until you leave the scope, which in this case is your Object_GetFirstProperty() of your wrapper. After that, the object is cleaned up and removed from the memory stack. FbxObject::GetFirstProperty() gives you a copy of the property, not an actual reference. Internally it might be different, but your wrapper is concerned about the property object itself, not it's content.
So what you are doing is you get a pointer to an address that is no longer valid later on when you pass it to your Property_GetName().
C++ behaves differently than C# in regards to object lifetime. An object in C# called MyObj can be thought of as a C++ pointer type like MyObject* - it's a like a reference value. In C# you have also value-types like struct and so forth, which are the equivalent to the C++ auto-variable. All auto-variables are destroyed when their lifetime scope is left.
What you'd have to do to overcome your problem is to save the object you get from FbxObject::GetFirstProperty() directly, and not a pointer to it. You'd basically have to marshall the object into a proper .NET class so that it's contents are not lost.
Alternatively, you could just allocate dynamic memory and copy the object you get from FbxObject::GetFirstPoperty() there, and return a pointer to your own memory. Of course you'd have to delete this memory later on manually. Here is a simple example:
FBXAPI FbxProperty* Object_GetFirstProperty(FbxObject* obj)
{
// Allocate custom memory.
char* myMem = new char[sizeof(FbxProperty)];
// Copy the property's content there.
std::memcpy(myMem, &obj->GetFirstProperty(), sizeof(FbxProperty));
// Return custom memory address.
return reinterpret_cast<FbxProperty*>(myMem);
}
This should solve your memory corruption issue. But in C++ you'd have to free this memory manually when your are finished with the property by doing ths:
FBXAPI void Property_Free(FbxProperty* prop)
{
// Free previously allocated memory
delete[] prop;
}
But this attempt may cause other problems, depending on how the actual FbxProperty handles it's data inside. You are creating a copy of the object, sure, but if the original temporaty/auto-variable deletes important memory upon destruction, you would have similar issus to the ones you have now.
If you are REALLY witty you could just write real wrapper classes for every FBX type you require and marshall the whole class type instead of generating separete C functions you have to P/Invoke every time you want to get a value or a property.

How to override what happens when boost::serialize gets a POINTER to an object

Hey so I understand boost serializes pointers automatically as long as you've defined the serialization function for the object it's pointing to, but
what do I do if I want to write a boost serialization function that takes a myClass pointer?
I don't want the boost to do the default action of saving the object that's pointed to and then restoring the pointer to point to that. I want the boost to do something different.
If you need a behaviour that is different from the normal pointer serialization for your special class, you have two options:
Maybe you can adjust the serialize() methods of all structs/classes that contain your myClass pointer in order to achieve the behaviour that you want. However, if you have many such pointers around, this won't be an option. Another possibility might be to use a free function as described in http://www.boost.org/doc/libs/1_47_0/libs/serialization/doc/index.html (written for the myClass pointer).
The other option only works if you are using no more than one archive type (e.g. the binary archive). You can derive from the archive classes and add an overload for the method save (and load, respectively).