Date: prev next · Thread: first prev next last
2014 Archives by date, by thread · List index


Hi,

Why does the attached patch lead to a segfault in "make
JunitTest_dbaccess_unoapi"? (The patch is against very recent master,
as in "I pushed right before hitting send on this email".)

Essentially, it changes, in code internal to a class,
Reference< XResultSet >
by
Reference< OResultSet >

Where XResultSet is one of the (several) UNO interfaces supported by
class OResultSet, which is itself a base class inherited by other
classes (it is connectivity::file::OResultSet, inherited by
connectivity::dbase::ODbaseResultSet and
connectivity::calc::OCalcResultSet and
connectivity::flat::OFlatResultSet).

And then it makes use of this extra typing information to get rid of
"silly" things like "oh, now I need the actual OResultSet pointer, so
I have to cast it back" and "I know this is a ORecordSet object that
implements XComponent, but the typing system doesn't, so I have to use
UNO_QUERY to get an XComponent interface".

My goal was:

1) To get the information in the typing system to make the code more
   readable, avoid all kinds of (hidden in Reference-handling)
   dynamic_cast, NULL-equality checks that I know will succeed, etc.

2) Not use raw/naked pointers to be exception-safe (which avoids me to
   think and find out whether any exception can be thrown there or
   not, and is good code hygiene).

*But* then it segfaults as soon as I try to construct a
Reference< OResultSet >
from a
OResultSet*
and that's how:

#2  0x00002acc39dbbb1b in connectivity::file::OResultSet::getDriverPos (this=0x2935670) at 
/home/master/src/libreoffice/workdirs/libreoffice-4-4/connectivity/source/drivers/file/FResultSet.cxx:1725
#3  0x00002acc39dacd21 in com::sun::star::uno::Reference<connectivity::file::OResultSet>::Reference 
(this=0x2acc2e9a54a0, pInterface=0x2935670) at 
/home/master/src/libreoffice/workdirs/libreoffice-4-4/include/com/sun/star/uno/Reference.hxx:137
#4  0x00002acc39da82b2 in connectivity::file::OPreparedStatement::makeResultSet 
(this=this@entry=0x292b750) at 
/home/master/src/libreoffice/workdirs/libreoffice-4-4/connectivity/source/drivers/file/FPreparedStatement.cxx:106
        xResultSet = uno::Reference to (connectivity::dbase::ODbaseResultSet *) 0x2935670

FPreparedStatement.cxx:106 is:
    Reference<OResultSet> xResultSet(createResultSet());

Reference.hxx:137 is the ->acquire() call in:
template< class interface_type >
inline Reference< interface_type >::Reference( interface_type * pInterface )
{
    _pInterface = castToXInterface(pInterface);
    if (_pInterface)
        _pInterface->acquire();
}

but it ends up in the wrong method, namely getDriverPos()! So my guess
is that it goes wrong in the "castToXInterface", but I don't
understand why. At first, I thought maybe it is related to
 "XInterface is an ambiguous base of connectivity::file::OResultSet"
but then, the comment around "castToXInterface" says that it is
designed to work "in the cases of multiple-inheritance interface types
(which inherit XInterface more than once)".

OTOH, it also says "In principle, this is not guaranteed to work. In
practice, it seems to work on all supported platforms." Maybe I'm just
hitting the practical version of this "in principle"?


And if I'm doing something that is "NOT ALLOWED" with
css::uno::Reference, what can I use as smart pointer to make all this
easy / clean / working? I tried using std::auto_ptr but that
segfaulted also (I think an implicit css::uno::Reference was created
when I assigned the pointer to a css::uno::WeakReference (namely the
member m_xResultSet), and this delete'd the object when going out of
scope), I understand I cannot use C++11 unique_ptr because we want to
be C++98-compatible (and it would probably have the same problem as
auto_ptr anyway).

-- 
Lionel
diff --git a/connectivity/source/drivers/file/FPreparedStatement.cxx 
b/connectivity/source/drivers/file/FPreparedStatement.cxx
index 2d7db2f..209a6b3 100644
--- a/connectivity/source/drivers/file/FPreparedStatement.cxx
+++ b/connectivity/source/drivers/file/FPreparedStatement.cxx
@@ -99,16 +99,15 @@ void OPreparedStatement::construct(const OUString& sql)  throw(SQLException, Run
     
OResultSet::setBoundedColumns(m_aEvaluateRow,aTemp,m_xParamColumns,xNames,false,m_xDBMetaData,m_aColMapping);
 }
 
-Reference<XResultSet> OPreparedStatement::makeResultSet()
+Reference<OResultSet> OPreparedStatement::makeResultSet()
 {
     closeResultSet();
 
-    OResultSet *pResultSet = createResultSet();
-    Reference<XResultSet> xRS(pResultSet);
-    initializeResultSet(pResultSet);
-    initResultSet(pResultSet);
-    m_xResultSet = xRS;
-    return xRS;
+    Reference<OResultSet> xResultSet(createResultSet());
+    m_xResultSet = xResultSet;
+    initializeResultSet(xResultSet.get());
+    initResultSet(xResultSet.get());
+    return xResultSet;
 }
 
 Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException, 
std::exception)
@@ -173,11 +172,10 @@ sal_Int32 SAL_CALL OPreparedStatement::executeUpdate(  ) throw(SQLException, 
Run
     ::osl::MutexGuard aGuard( m_aMutex );
     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
 
-    Reference<XResultSet> xRS(makeResultSet());
+    Reference<OResultSet> xRS(makeResultSet());
     if(xRS.is())
     {
-        assert(dynamic_cast<OResultSet*>(xRS.get()));
-        const sal_Int32 res(static_cast<OResultSet*>(xRS.get())->getRowCountResult());
+        const sal_Int32 res(xRS->getRowCountResult());
         // nobody will ever get that ResultSet...
         Reference< XComponent > xComp(xRS, UNO_QUERY);
         assert(xComp.is());
diff --git a/connectivity/source/inc/file/FPreparedStatement.hxx 
b/connectivity/source/inc/file/FPreparedStatement.hxx
index e380c84..a15cf6f 100644
--- a/connectivity/source/inc/file/FPreparedStatement.hxx
+++ b/connectivity/source/inc/file/FPreparedStatement.hxx
@@ -53,7 +53,7 @@ namespace connectivity
 
             // factory method for resultset's
             virtual OResultSet* createResultSet() SAL_OVERRIDE;
-            ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > makeResultSet();
+            ::com::sun::star::uno::Reference< OResultSet > makeResultSet();
             void initResultSet(OResultSet*);
 
             void checkAndResizeParameters(sal_Int32 parameterIndex);

Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.