On 2019-12-05 12:01, Jiří Činčura wrote:
Maybe better to show some code (simplified). Expecting the free and release to
have separate responsibilities I wrote initially (the variables with underscore
are class fields). The Execute is called at some point and Free is called
either after the IExternalFunctionImpl finished executing or in
IExternalResultSetImpl::dispose (because that's the only place I'm aware of I
know no more fetching will occur and the fetching might end up in the middle
not reading all the results (otherwise I would know it because fetchNext would
return != IStatus::RESULT_OK).
void Execute(const char* stmt)
{
auto status = ThrowStatusWrapper(_context->getMaster()->getStatus());
_attachment = _context->getAttachment(&status);
_transaction = _context->getTransaction(&status);
_statement = _attachment->prepare(&status, _transaction, 0, stmt,
SQL_DIALECT_CURRENT, 0);
_cursor = _statement->openCursor(&status, _transaction, nullptr,
nullptr, outMetadata, 0);
_msg = new unsigned char[outMetadata->getMessageLength(&status)];
// other method does the fetchNext
}
void Free()
{
_cursor->close(&status);
_statement->free(&status);
delete _msg;
_msg = nullptr;
_cursor->release();
You are a kind of lucky that you did not reach this point of code -
calling release() after successful close() of cursor is illegal, can
easily cause segfault.
_cursor = nullptr;
_statement->release();
_statement = nullptr;
Answering next eMail - this code with _transaction & _attachment is
absolutely OK, all you need here is to decrement counters.
_transaction->release();
_transaction = nullptr;
_attachment->release();
_attachment = nullptr;
}
I suggest the following for cursor (almost same for statement):
try
{
_cursor->close(&status);
}
catch (const FbException& ex)
{
// report error code
_cursor->release();
}
_cursor = nullptr;
Firebird-Devel mailing list, web interface at
https://lists.sourceforge.net/lists/listinfo/firebird-devel