segfault happens when I serialize nested class in apache module - serialization

Serializing simple class "A" in Apache module done without error but when I tried to serialize my complex object like "X" which has a member, type of "A", I got segfault in Apache module. ( this doesn't happen to a executable console application )
------------------------- here is my code : ---------------------
class A {
private:
friend class boost::serialization::access; // to enable boost "access" class to call private "serialize" method of class "A"
template<class ArchT>
void serialize(ArchT &ar, unsigned int version) { // method for both serializing and deserializing
ar & memA; // (de)serialize member "memA"
}
std::string memA; // sample member
public:
A(){}
A(std::string pmemA) :
memA(pmemA) {
}
std::string GetMemA()
{
return memA;
}
};
class X {
private:
friend class boost::serialization::access;
template<class ArchT>
void serialize(ArchT &ar, unsigned int version) {
ar & memX;
ar & a;
}
std::string memX;
A a;
public:
X(std::string pmemX, A pa) :
memX(pmemX), a(pa) {
}
X(){}
};
-------------------
string st=GetRandomFileName();
ofstream out(st.c_str());
boost::archive::text_oarchive out_r(out);
A a("Amem");
X x("Xmem", a);
out_r << x; // not works
out_r << a; // works!
------------------- here is stack trace from gdb for apache ----------------
boost::serialization::typeid_system::extended_type_info_typeid_0::is_less_than(boost::serialization::extended_type_info const&) const () from /tmp/libIRSProWebApacheModule.so
2 0xb7223c61 in std::_Rb_tree

Related

Boost serialization and pointers to parent class

Assuming the following simplified code:
Parent class
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/unique_ptr.hpp>
class Parent
{
public:
Parent();
...
private:
// boost serialization
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & *m_child;
}
std::unique_ptr<Child> m_child;
}
Parent::Parent()
{
...
m_child = std::unique_ptr<Child>(new Child(this));
}
Child class
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/unique_ptr.hpp>
class Child
{
public:
Child(Parent * parent)
{
m_parent = parent;
};
...
private:
// boost serialization
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & m_parent;
}
Child(){};
Parent m_parent{ nullptr };
}
My parent class creates a child class and passes a pointer to itself stored by the child.
When archiving the parent class, it archives the child which archives the pointer to the parent.
When restoring the parent class, it creates the child class and restores it as well. My question is this:
Will the pointer in the child class get restore properly so it is guaranteed to point to it's parent?
This SEEMS to work which I've verified by stepping through the debugger and comparing the values of the Parent's this pointer with the child's m_parent. However, I can't figure out how boost pulls this off and it makes me wonder if I'm just 'getting lucky'. Can anyone verify that boost serialization is smart enough to maintain the child::m_parent->parent relationship?
Or should I be taking the extra step of not archiving the pointer and setting it after loading the object?
Two things:
Object Tracking facilitates this. Object Tracking is enabled by default when serializing pointers.
No, you do not serialize the unique_ptr like that.
In fact, there's little reason to serialize the m_parent of the child, either, because the parent can set the self-reference from within the load handler.
But assuming that you want the easy way, let's stick with that idea and make it work due to Object Tracking
DEMO
I included some tricks to demonstrate that deserialization
correct de-duplicates pointers to the same object
restores the member pointers even if we forcefully "break" the invariants prior to deserialization
Live On Coliru
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/unique_ptr.hpp>
#include <memory>
#include <sstream>
#include <iostream>
class Parent;
class Child {
public:
Child(Parent *parent)
: m_parent(parent), m_duplicate_parent(parent) {}
Parent *m_parent { nullptr };
Parent *m_duplicate_parent{ nullptr };
private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, unsigned) {
ar & m_parent & m_duplicate_parent;
}
Child() = default;
};
class Parent {
public:
Parent() : m_child(std::make_unique<Child>(this)) {}
//private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, unsigned) {
ar & m_child;
}
std::unique_ptr<Child> m_child;
};
int main() {
std::stringstream ss;
{
boost::archive::text_oarchive oa(ss);
Parent p;
assert(&p == p.m_child->m_parent);
assert(&p == p.m_child->m_duplicate_parent);
oa << p;
}
std::cout << ss.str();
{
boost::archive::text_iarchive ia(ss);
Parent p;
// let's purposelly break the invariants so we know deserialization
// does restore them as required, and we not just "getting lucky":
p.m_child->m_parent = nullptr;
p.m_child->m_duplicate_parent = nullptr;
assert(&p != p.m_child->m_parent);
assert(&p != p.m_child->m_duplicate_parent);
// nuclear:
p.m_child.reset();
// now deserialize
ia >> p;
assert(&p == p.m_child->m_parent);
assert(&p == p.m_child->m_duplicate_parent);
}
}
Prints something similar to
22 serialization::archive 15 1 0
0 0 0 2 1 0
1 0 0 0 0

How to access private variable in C++/CLI managed class

//MyWrapper.h
#include "arithmetic.h"
#include "mathematics.h"
namespace MyWrapper {
public ref class ClassA
{
public:
ClassA();
~ClassA();
int add(int, int);
private:
MyEngine::Arithmetic *nativeClassA;
}
public ref class ClassB
{
public:
ClassB(ClassA^ arith);
~ClassB();
int pow(int, int);
private:
MyEngine::Mathematics *nativeClassB;
}
}
//MyWrapper.cpp
#include "MyWrapper.h"
My::ClassA::ClassA()
{
nativeClassA = new MyEngine::Arithmetic();
}
My::ClassA::~ClassA()
{
delete nativeClassA;
}
int My::ClassA::add(int a, int b)
{
return nativeClassA->add(a, b);
}
My::ClassB::ClassB(ClassA^ classA)
{
nativeClassB = new MyEngine::Mathematics(classA->nativeClassA); //***Error***
}
My::ClassB::~ClassB()
{
delete nativeClassB;
}
int My::ClassB::pow(int a, int b)
{
int result = nativeClassB->pow(a, b);
return result;
}
Here, Mathematics class need to init with Arithmetic class.
But nativeClassA is private variable in ClassA.
So nativeClassB = new MyEngine::Mathematics(classA->nativeClassA); , it will occurs compile error.
So I changed the nativeClassA to public.
But at that time, nativeClassA will export to c#.
I don't want to export nativeClassA variable to c#.
How can I fix it?
Thanks in advice.
Since you're writing a managed class, you can use all the access modifiers that C# has. This seems like a perfect scenario for internal. (The linked documentation is for C#, but it's the same keyword in C++/CLI.)

How to serialize std::chrono::duration with Boost?

Is it possible to serialize std::chrono::duration or especially std::chrono::milliseconds with boost::serialization?
The following error occurred:
"struct std::chrono::duration >’ has no member named ‘serialize"
I need this for my template-class:
#include <iostream>
#include <chrono>
#include <boost/serialization/serialization.hpp>
template<typename T>
class Field {
public:
// Default Constructor
Field() {}
Field(std::string name, T value) :
mName(name), mValue(value) {}
~Field() {}
const std::string& getName() const {
return mName;
}
T getValue() const {
return mValue;
}
private:
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive& archive, const unsigned int) {
archive & boost::serialization::make_nvp("Name", mName);
archive & boost::serialization::make_nvp("Value", mValue);
}
std::string mName;
T mValue;
};
BOOST_CLASS_IMPLEMENTATION( Field<int>, boost::serialization::object_serializable )
BOOST_CLASS_IMPLEMENTATION( Field<std::chrono::milliseconds>, boost::serialization::object_serializable )
I'm creating the following object:
Field<std::chrono::milliseconds> mSimTime;
Let's say you have:
auto earlier = std::chrono::system_clock::now();
auto now = std::chrono::system_clock::now();
auto aLotOfMilliseconds= std::chrono::duration_cast<std::chrono::milliseconds>(
now - earlier);
// Serialize here int64_t.
then after deserialization, you have:
std::chrono::duration<int64_t, std::milli> duration(aLotOfMilliseconds);

Call c++ code in c# by a cli wrapper

I have a c++ code that needs to be called in c# by a cli wrapper. I am stuck at the operator overloading part.
//this is my code
//Cppclass.h
#ifdef CPP_EXP_EXPORTS
#define CPP_EXP __declspec(dllexport)
#else
#define CPP_EXP __declspec(dllimport)
#endif
class CPP_EXP Cppclass;
CPP_EXP Cppclass operator-(Cppclass const &, Cppclass const &);
class CPP_EXP Cppclass
{
public:
friend CPP_EXP Cppclass operator-(Cppclass const &, Cppclass const &);
};
//this is my managed c++ code.
#include "Cppclass.h"
namespace Wrapper
{
public ref class cppwrapclass
{
public:
static cppwrapclass ^ operator-(cppwrapclass%A,cppwrapclass%B)
{
operator-(A.obj,B.obj);
return gcnew cppwrapclass();
}
private:
Cppclass *obj;
};
}
Its showing an intellisense error and not getting compiled.
You write a wrapper like this:
public ref class cppwrapclass
{
public:
cppwrapclass(Cppclass *obj)
: obj(obj)
{
}
~cppwrapclass()
{
this->!cppwrapclass();
}
!cppwrapclass()
{
if (obj)
{
delete obj;
obj = nullptr;
}
}
static cppwrapclass^ operator-(cppwrapclass% A, cppwrapclass% B)
{
return gcnew cppwrapclass(new Cppclass(*A.obj - *B.obj));
}
private:
Cppclass* obj;
};
A.obj is of type Cppclass*, therefore *A.obj is of type Cppclass, and *A.obj - *B.obj is a temporary Cppclass which needs to be moved to the heap in order to be referenced by the wrapper, hence the copy constructor call: new Cppclass(*A.obj - *B.obj).
The rest is the Dispose pattern and finalizer plumbing code.

Why a serializable class must have the function that get the instance from class name?

Such as mfc, it should add
DECLARE_SERIAL(CGraph)
If I a have a class,
class A
{
int a,b;
};
I can store the value of a and b to a file ,then read it.
So I couldn't understand why DECLARE_SERIAL(CGraph) used.
The DECLARE_SERIAL and IMPLEMENT_SERIAL macros are only necessary for classes derived from CObject that you wish to serialize polymorphically using the framework provided by MFC.
If your class is not derived from CObject and/or you do not wish to use MFC's serialization polymorphically (i.e. via a pointer to CObject), then of course you can implement your own solution as you rightly say.
For example, DECLARE_SERIAL(CMyClass) expands to the following code that goes in your class declaration
protected:
static CRuntimeClass* __stdcall _GetBaseClass();
public:
static CRuntimeClass classCMyClass;
static CRuntimeClass* __stdcall GetThisClass();
virtual CRuntimeClass* GetRuntimeClass() const;
static CObject* __stdcall CreateObject();
friend CArchive& __stdcall operator>>(CArchive& ar, CMyClass* &pOb);
and IMPLEMENT_SERIAL(CMyClass, CObject, VERSIONABLE_SCHEMA | 1) expands to the following code that goes in the cpp file
CObject* __stdcall CMyClass::CreateObject()
{
return new CMyClass;
}
extern AFX_CLASSINIT _init_CMyClass;
CRuntimeClass* __stdcall CMyClass::_GetBaseClass()
{
return (CObject::GetThisClass());
}
__declspec(selectany) CRuntimeClass CMyClass::classCMyClass =
{
"CMyClass", sizeof(class CMyClass), (0x80000000) | 1,
CMyClass::CreateObject, &CMyClass::_GetBaseClass, 0, &_init_CMyClass
};
CRuntimeClass* __stdcall CMyClass::GetThisClass()
{
return ((CRuntimeClass*)(&CMyClass::classCMyClass));
}
CRuntimeClass* CMyClass::GetRuntimeClass() const
{
return ((CRuntimeClass*)(&CMyClass::classCMyClass));
}
AFX_CLASSINIT _init_CMyClass((CMyClass::GetThisClass()));
CArchive& __stdcall operator>>(CArchive& ar, CMyClass* &pOb)
{
pOb = (CMyClass*) ar.ReadObject((CMyClass::GetThisClass()));
return ar;
}
As it says in MSDN it is also possible to use serialization without using the above macros: