C++ MySql 连接器 - 查询超出范围的结果

C++ MySql Connector - results from query going out of scope

我遇到了 C++ mysql 连接器查询执行结果的范围问题。

在下面的代码中,ResultSet * 结果是从另一个函数传递的,最初是 NULL;然而,在执行行 result = statement->executeQuery( query ) 之后,结果不再是 NULL.

table 也没有打印错误。

从该函数返回时出现问题。 ResultSet * 结果从不 NULL 变为等于 NULL.

显然,sql 查询结果存在某种形式的范围界定。也许他们的函数正在返回对局部变量的引用(否则真的不确定)?

如何解决这个范围问题,以便 classes/functions 调用此函数可以随心所欲地处理结果并减少在此包装器中编写一堆专用函数的需要?此外,副本应该被最小化——因此使用指针。

bool MySQLConnector::ExecuteQuery( std::string query, sql::ResultSet * result )
{

   //connection is a member variable and has been initialized
   sql::Statement * statement = connection->createStatement();

   try
   {
       result = statement->executeQuery( query );
   }
   catch( sql::SQLException &e )
   {
      //handle errors
   }

   delete statement;

   if( result == NULL )
   {
       printf( "Result is null File: %s Line %i\n", __FILE__, __LINE__ );
       return false;
   }
   else
   {
        printf("Result is not null File: %s Line %i\n", __FILE__, __LINE__ );
   }

   return true;
}

如果我有一个函数 foo 可以使用正确的参数调用上面的函数。 printf 声明结果不为空将打印,但在 foo 中,在 ExecuteQuery 执行后,传递给函数的指针变为 NULL.

有几个问题:

1. result 是传值

您按值传递 result。这意味着该函数会收到您在调用该方法时传递的指针的副本。

例如,如果调用 ExecuteQuery 的代码如下所示:

std::string query("SELECT ...");
sql::ResultSet *result = NULL;
ExecuteQuery(query, result);

那么 ExecuteQuery 不能改变 result 的值,因为它被复制到方法中。 如果你想改变它的值,你应该传递一个对结果的引用。您可以通过将 ExecuteQuery 更改为:

来做到这一点
bool MySQLConnector::ExecuteQuery( std::string query, sql::ResultSet *& result )

然后,ExecuteQuery 操作原始指针,而不是副本。

2。 MySQL C++ API 在删除 Statement 时释放 ResultSet

就像@nos 指出的那样,当您调用 delete statement 时,您还释放了保存 result 信息的资源。

result 仍将具有有效值,因为它不知道已释放的内存,但如果您访问它,可能会导致分段错误。

处理此问题的正确方法是:

  • 复制结果
  • 让调用者也传递一个语句对象,并在使用结果中的值后释放它。
bool MySQLConnector::ExecuteQuery( std::string query, sql::ResultSet * result )
                                                                     ^^^^^^^^

在这里,result 很像函数中的局部变量,它包含调用者变量的副本

当您在 ExecuteQuery 中对其赋值时,它只会影响函数内的变量,不会影响调用者的变量。

您可以改为将其设为引用,这样它将引用调用者的变量,如下所示:

bool MySQLConnector::ExecuteQuery( std::string query, sql::ResultSet *&result )

另一种方法是传入一个指向变量的指针(由于变量本身就是一个指针,因此您将处理一个指向指针的指针)。这使您还可以修改调用者的指针:

 bool MySQLConnector::ExecuteQuery( std::string query, sql::ResultSet **result ) {
 ...
     *result = statement->executeQuery( query );

这也需要对调用者进行修改,因此它传入一个指向其局部变量的指针,例如

sql::ResultSet *rs;
c->ExecuteQuery("select ...", &rs);