c++oraclevisual-studio-2012occi

VS2012 Returning vector of Oracle unique_ptr´s crash


I do have a code structure where I read Oracle rows from database and I do assign then to a common model that represents its data (called commonmodel::Model). I´m using VS2012 on Windows 7.

My issue is with this piece of code below, where I do execute some statement like SELECT ...

I´m running for test and the tables are empty, so no data is returned from SELECT....from database, thus the piece of code inside while (resultSet->next()) is not being called.

My program compiles, but it crashes at runtime on returnin data (return retData). I have no idea what´s causing this behaviour and I would like help to solve it.

BTW: I choose to create std::unique_ptr´s for Oracle pointers so that I can leave to the compiler to free these pointers when not needed any mode. In that wat I don´t need to delete them at the end of the operation.

std::vector<std::unique_ptr<commonmodel::Model>> OracleDatabase::ExecuteStmtReturningData(std::string sql, int& totalRecords, commonmodel::Model &modelTemplate)
{
    std::unique_ptr<oracle::occi::Statement> stmt(connection->createStatement());
    stmt->setAutoCommit(TRUE);
    std::unique_ptr<oracle::occi::ResultSet> res(stmt->executeQuery(sql));

    std::vector<std::unique_ptr<commonmodel::Model>> ret = getModelsFromResultSet(res, modelTemplate);

    return ret;
}

std::vector<std::unique_ptr<commonmodel::Model>> OracleDatabase::getModelsFromResultSet(std::unique_ptr<oracle::occi::ResultSet>& resultSet, commonmodel::Model &modelTemplate)
{
    std::vector<std::unique_ptr<commonmodel::Model>> retData;

    std::vector<oracle::occi::MetaData> resultMeta = resultSet->getColumnListMetaData();

    while (resultSet->next())
    {
         std::unique_ptr<commonmodel::Model> model = modelTemplate.clone();

         for (unsigned int i = 1; i <= resultMeta.size(); i++) // ResultSet starts with one, not zero
         {
             std::string label = resultMeta.at(i).getString(oracle::occi::MetaData::ATTR_NAME);
             setPropertyFromResultSet(resultSet, label, i, *model);
         }

         retData.push_back(std::move(model)); // unique_ptr can only be copied or moved.
     }


    return retData; <<<==== CRASH ON RETURN....
}

Solution

  • You can't use 'stock' unique_ptr to deal with OCCI objects and pointers. OCCI doesn't want to you to delete those pointers (this is what unique_ptr is going to do), instead, they want you to free them using OCCI-provided mechanisms.

    In particular, to free Statement object you should use Connection::terminateStatement. Same for ResultSet*, and any other OCCI pointer for this matter.

    Now, you can supply custom deleter into unique_ptr object, but the issue there is that you'd need to use a pointer to already existing 'parent' object for this - and it is hard to manage lifetime of independent pointers in such a way.

    On a side note, I strongly advise against using OCCI. It is a very badly designed, not properly documented library. OCI provides a much better choice.