pocoproject / poco

The POCO C++ Libraries are powerful cross-platform C++ libraries for building network- and internet-based applications that run on desktop, server, mobile, IoT, and embedded systems.
https://pocoproject.org
Other
8.05k stars 2.11k forks source link

RecordSet issue since 1.10.0 #4525

Open petko opened 2 months ago

petko commented 2 months ago

Describe the bug I get a weird bug with RecordSet when running my tests in debug builds in Visual C++Builder 2019. It works in release builds.

Until Poco 1.9.4 the code using the ExecuteSelectStatementFails function worked properly. Starting with Poco 1.10.0 is shows the following error (currently running Poco 1.12.5p2):

3>minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp(904) : Assertion failed: _CrtIsValidHeapPointer(block)
3>minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp(908) : Assertion failed: is_block_type_valid(header->_block_use)

To Reproduce I have a simple test in GTest:

#include <Poco/Data/RecordSet.h>
#include <Poco/Data/SessionFactory.h>
#include <Poco/Data/SQLite/Connector.h>

using namespace Poco;
using namespace Poco::Data;
using namespace Poco::Data::Keywords;
using namespace Poco::Data::SQLite;

//-------------------------------------------------------------------------------------------------
RecordSet ExecuteSelectStatementWorks(Session& session, const std::string& sql)
{
    Statement select(session);
    select << sql;
    select.execute();

    // return directly
    return RecordSet(select);
}

//-------------------------------------------------------------------------------------------------
RecordSet ExecuteSelectStatementFails(Session& session, const std::string& sql)
{
    Statement select(session);
    select << sql;
    select.execute();

    // return temp copy
    RecordSet recordSet(select);
    return recordSet;
}

//-------------------------------------------------------------------------------------------------
TEST(PocoSqliteTest, ExecutesSelectStatement)
{
    SQLite::Connector::registerConnector();

    Session session("SQLite", ":memory:");

    auto recordSet = ExecuteSelectStatementFails(session, "SELECT sqlite_version()");

    ASSERT_TRUE(recordSet.moveFirst());

    SQLite::Connector::unregisterConnector();
}

Expected behavior I expect calling any of ExecuteSelectStatementWorks and ExecuteSelectStatementFails in the test to work properly.

Please add relevant environment information: Visual C++ 2019 (latest update) in Windows 10

Additional context I suspect that the reason is that one is using copy semantics and one is using move semantics and there is a bug in Poco starting with Poco 1.10.0. This version of Poco introduced C++14 support and the move assignment operator for RecordSet.