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);
_______________________________________________ LibreOffice mailing list LibreOffice@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice