qx::clone failure

Open discussion on QxOrm library

Re: qx::clone failure

Postby qxorm » Tue Nov 08, 2016 9:34 pm

the difference is that I use boost::shared_ptr<T> instead of QSharePointer<T>, but it should be the same thing.

In fact, I think this is the problem !
The boost serialization of a QSharedPointer<T> doesn't take into account several smart-pointers on a same raw instance.
The boost serialization of a boost::shared_ptr<T> doesn't have this problem.

So this is a bug of QxOrm library, in the file : ./include/QxSerialize/Qt/QxSerialize_QSharedPointer.h
Could you please try this patch :
Code: Select all
/****************************************************************************
**
** http://www.qxorm.com/
** Copyright (C) 2013 Lionel Marty (contact@qxorm.com)
**
** This file is part of the QxOrm library
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any
** damages arising from the use of this software
**
** Commercial Usage
** Licensees holding valid commercial QxOrm licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Lionel Marty
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file 'license.gpl3.txt' included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met : http://www.gnu.org/copyleft/gpl.html
**
** If you are unsure which license is appropriate for your use, or
** if you have questions regarding the use of this file, please contact :
** contact@qxorm.com
**
****************************************************************************/

#ifdef _QX_ENABLE_BOOST_SERIALIZATION
#ifndef _QX_SERIALIZE_QSHAREDPOINTER_H_
#define _QX_SERIALIZE_QSHAREDPOINTER_H_

#ifdef _MSC_VER
#pragma once
#endif

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/version.hpp>
#include <boost/serialization/nvp.hpp>

#include <QtCore/qsharedpointer.h>
#include <QtCore/QWeakPointer>
#include <QtCore/qhash.h>

namespace boost {
namespace serialization {

template <class Archive, typename T>
inline void save(Archive & ar, const QSharedPointer<T> & t, const unsigned int file_version)
{
   Q_UNUSED(file_version);
   const T * ptr = t.data();
   ar << boost::serialization::make_nvp("qt_shared_ptr", ptr);
}

template <class Archive, typename T>
inline void load(Archive & ar, QSharedPointer<T> & t, const unsigned int file_version)
{
   Q_UNUSED(file_version);
   static QHash<void *, QWeakPointer<T> > listOfWeakPointers;
   T * ptr = NULL; ar >> boost::serialization::make_nvp("qt_shared_ptr", ptr);
   if (! ptr) { t = QSharedPointer<T>(); return; }

   void * pVoid = static_cast<void *>(ptr);
   QSharedPointer<T> pShared = (listOfWeakPointers.contains(pVoid) ? listOfWeakPointers.value(pVoid).toStrongRef() : QSharedPointer<T>());
   if (pShared) { t = pShared; return; }
   t = QSharedPointer<T>(ptr);
   QWeakPointer<T> pWeak = t;
   listOfWeakPointers.insert(pVoid, pWeak);

   static int iLoadCount = 0;
   iLoadCount++; if (iLoadCount <= 1000) { return; }
   QMutableHashIterator<void *, QWeakPointer<T> > itr(listOfWeakPointers);
   while (itr.hasNext()) { itr.next(); if (itr.value().isNull()) { itr.remove(); } }
   iLoadCount = 0;
}

template <class Archive, typename T>
inline void serialize(Archive & ar, QSharedPointer<T> & t, const unsigned int file_version)
{
   boost::serialization::split_free(ar, t, file_version);
}

} // namespace boost
} // namespace serialization

#endif // _QX_SERIALIZE_QSHAREDPOINTER_H_
#endif // _QX_ENABLE_BOOST_SERIALIZATION


Just replace QxSerialize_QSharedPointer.h file content with this code, then rebuild QxOrm library and your project.
I have not tested it, so could you please let me know if it compiles and if it resolves your issue ?
qxorm
Site Admin
 
Posts: 481
Joined: Mon Apr 12, 2010 7:45 am

Re: qx::clone failure

Postby Kasuax » Wed Nov 09, 2016 3:53 am

Ok so this fix seems to have taken care of the duplicate items! Well done! Unfortunately my empty lists are now crashing...

Code: Select all
1  QBasicAtomicInt::deref                                                           qatomic_windows.h        324  0x66c0862d
2  QList<QSharedPointer<QXC::GlobalKey>>::~QList<QSharedPointer<QXC::GlobalKey>>    qlist.h                  731  0xf6a84e2 
3  QXC::Project::~Project                                                           QXC_Project.gen.cpp      117  0xfb68005 
4  QXC::Project::`vector deleting destructor'                                       QXC                           0xf6921c0 
5  QtSharedPointer::ExternalRefCount<QXC::Project>::deref                           qsharedpointer_impl.h    342  0x13b2bc8 
6  QtSharedPointer::ExternalRefCount<QXC::Project>::deref                           qsharedpointer_impl.h    336  0x13b2ab9 
7  QtSharedPointer::ExternalRefCount<QXC::Project>::~ExternalRefCount<QXC::Project> qsharedpointer_impl.h    401  0x13b29df 
8  QSharedPointer<QXC::Project>::~QSharedPointer<QXC::Project>                      CCT                           0x13b292f 
9  LandingPage::onProjectExport                                                     landingpage.cpp          339  0x13c546a 
10 LandingPage::qt_static_metacall                                                  moc_landingpage.cpp      63   0x14fefda 
11 QMetaObject::activate                                                            qobject.cpp              3567 0x66df1931
12 ProjectSelectorView::projectExport                                               moc_projectselector.cpp  126  0x150e1f1 
13 ProjectSelectorView::onProjectExport                                             projectselector.cpp      104  0x14b1f60 
14 ProjectSelectorView::qt_static_metacall                                          moc_projectselector.cpp  68   0x150e006 
15 QMetaObject::activate                                                            qobject.cpp              3567 0x66df1931
16 QAction::triggered                                                               moc_qaction.cpp          276  0x64773d4b
17 QAction::activate                                                                qaction.cpp              1259 0x64773291
18 QMenuPrivate::activateCausedStack                                                qmenu.cpp                1039 0x64d808bc
19 QMenuPrivate::activateAction                                                     qmenu.cpp                1132 0x64d80c1b
20 QMenu::mouseReleaseEvent                                                         qmenu.cpp                2372 0x64d843fb
21 QWidget::event                                                                   qwidget.cpp              8390 0x64819394
22 QMenu::event                                                                     qmenu.cpp                2481 0x64d8496b
23 QApplicationPrivate::notify_helper                                               qapplication.cpp         4565 0x6479710e
24 QApplication::notify                                                             qapplication.cpp         4108 0x64795440
25 QCoreApplication::notifyInternal                                                 qcoreapplication.cpp     953  0x66dceb41
26 QCoreApplication::sendSpontaneousEvent                                           qcoreapplication.h       234  0x66e761c8
27 QApplicationPrivate::sendMouseEvent                                              qapplication.cpp         3171 0x6479403a
28 QETWidget::translateMouseEvent                                                   qapplication_win.cpp     3295 0x64854922
29 QtWndProc                                                                        qapplication_win.cpp     1709 0x648503db
30 gapfnScSendMessage                                                               USER32                        0x75ed62fa
31 GetThreadDesktop                                                                 USER32                        0x75ed6d3a
32 CharPrevW                                                                        USER32                        0x75ed77c4
33 DispatchMessageW                                                                 USER32                        0x75ed788a
34 QEventDispatcherWin32::processEvents                                             qeventdispatcher_win.cpp 823  0x66e17f76
35 QGuiEventDispatcherWin32::processEvents                                          qapplication_win.cpp     1212 0x6484eeee
36 QEventLoop::processEvents                                                        qeventloop.cpp           150  0x66dcbf7e
37 QEventLoop::exec                                                                 qeventloop.cpp           204  0x66dcc106
38 QMenu::exec                                                                      qmenu.cpp                2125 0x64d8356f
39 QMenu::exec                                                                      qmenu.cpp                2160 0x64d83676
40 QWidget::event                                                                   qwidget.cpp              8576 0x64819af7
41 QAbstractButton::event                                                           qabstractbutton.cpp      1083 0x64cbe8ff
42 QPushButton::event                                                               qpushbutton.cpp          684  0x64d97c6b
43 QCommandLinkButton::event                                                        qcommandlinkbutton.cpp   309  0x64cf3ec3
44 QApplicationPrivate::notify_helper                                               qapplication.cpp         4565 0x6479710e
45 QApplication::notify                                                             qapplication.cpp         4187 0x647959d3
46 QCoreApplication::notifyInternal                                                 qcoreapplication.cpp     953  0x66dceb41
47 QCoreApplication::sendSpontaneousEvent                                           qcoreapplication.h       234  0x66e761c8
48 QETWidget::translateMouseEvent                                                   qapplication_win.cpp     3390 0x64854ec9
49 QtWndProc                                                                        qapplication_win.cpp     1709 0x648503db
50 gapfnScSendMessage                                                               USER32                        0x75ed62fa
51 GetThreadDesktop                                                                 USER32                        0x75ed6d3a
52 CharPrevW                                                                        USER32                        0x75ed77c4
53 DispatchMessageW                                                                 USER32                        0x75ed788a
54 QEventDispatcherWin32::processEvents                                             qeventdispatcher_win.cpp 823  0x66e17f76
55 QGuiEventDispatcherWin32::processEvents                                          qapplication_win.cpp     1212 0x6484eeee
56 QEventLoop::processEvents                                                        qeventloop.cpp           150  0x66dcbf7e
57 QEventLoop::exec                                                                 qeventloop.cpp           204  0x66dcc106
58 QCoreApplication::exec                                                           qcoreapplication.cpp     1225 0x66dcf07d
59 QApplication::exec                                                               qapplication.cpp         3824 0x64794a98
60 main                                                                             main.cpp                 15   0x138dc81 
61 WinMain                                                                          qtmain_win.cpp           131  0x15add0a 
62 __tmainCRTStartup                                                                crtexe.c                 547  0x15ad350 
63 WinMainCRTStartup                                                                crtexe.c                 371  0x15ad0df 
64 BaseThreadInitThunk                                                              kernel32                      0x772b336a
65 RtlInitializeExceptionChain                                                      ntdll                         0x77949902
66 RtlInitializeExceptionChain                                                      ntdll                         0x779498d5
Kasuax
 
Posts: 62
Joined: Mon Jun 20, 2016 6:42 pm

Re: qx::clone failure

Postby qxorm » Wed Nov 09, 2016 8:19 am

this fix seems to have taken care of the duplicate items! Well done!

Great ! Thx for your tests : I will add this fix for the next version of QxOrm library (will be released soon with the new version of QxEntityEditor).

Unfortunately my empty lists are now crashing...

I think that your issue is now the double deletion of the root item of your tree (see my first answers in this topic for more details).
Could you please provide your source code to show how you call qx::clone() function ?
Could you please try to use this code to protect your root item :
Code: Select all
boost::shared_ptr<myClass> * pCloneTemp = qx::clone_to_nude_ptr(other);
boost::shared_ptr<myClass> pClone = (pCloneTemp ? (* pCloneTemp) : boost::shared_ptr<myClass>());
if (pCloneTemp) { delete pCloneTemp; pCloneTemp = NULL; }
// Now use pClone....


Note : I will add this tip to protect the root item when cloning smart-pointers in the QxOrm manual here : http://www.qxorm.com/qxorm_en/manual.html#manual_640
qxorm
Site Admin
 
Posts: 481
Joined: Mon Apr 12, 2010 7:45 am

Re: qx::clone failure

Postby Kasuax » Mon Nov 14, 2016 7:53 pm

I have integrated your hot fix and I also am using your safe clone technique to guard against the root item. While testing I also discovered something on my end which may have been producing the double reference in the first place. Unfortunately now I have run into a new issue.

If I take my root object and recursively insert it into the database I get a brand new copy in the database. This is ideal!
If I take my root object, clone it, and then try to insert it, I get a copy in the database but many of the children relationships still point to the old root object in the database.
I've attached a screenshot for reference.

I've also tried playing around with the following setting which I currently have set to false. Setting it to true didn't change anything.
qx::QxSqlDatabase::getSingleton()->setForceParentIdToAllChildren(false);

Any thoughts here?
Attachments
Capture.JPG
Database References
Capture.JPG (96.81 KiB) Viewed 17575 times
Kasuax
 
Posts: 62
Joined: Mon Jun 20, 2016 6:42 pm

Re: qx::clone failure

Postby qxorm » Tue Nov 15, 2016 7:48 am

What you could try is :

1- Put this settings :
Code: Select all
qx::QxSqlDatabase::getSingleton()->setForceParentIdToAllChildren(true);


2- Use qx::dao::save_with_relation_recursive() function with qx::dao::save_mode::e_insert_only parameter, something like this :
Code: Select all
QSqlError daoError = qx::dao::save_with_relation_recursive(myTree, qx::dao::save_mode::e_insert_only);


Unfortunately now I have run into a new issue.

Next time please create a new topic.
Your clone crash seems to be resolved.
qxorm
Site Admin
 
Posts: 481
Joined: Mon Apr 12, 2010 7:45 am

Re: qx::clone failure

Postby Kasuax » Tue Nov 15, 2016 2:31 pm

Thank you for your reply, sorry about stealing the topic.
Kasuax
 
Posts: 62
Joined: Mon Jun 20, 2016 6:42 pm

Previous

Return to QxOrm - Open discussion

Who is online

Users browsing this forum: No registered users and 2 guests

cron