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

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

本文关键字:范围 结果 连接器 查询 C++MySql      更新时间:2023-10-16

我在执行C++mysql连接器查询的结果时遇到了作用域问题。

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

表中也没有打印错误。

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

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

我该如何绕过这个作用域问题,以便调用该函数的类/函数可以随心所欲地处理结果,并减轻在该包装器中编写一堆专用函数的需要?此外,应尽量减少副本,因此应使用指针。

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 %in", __FILE__, __LINE__ );
return false;
}
else
{
printf("Result is not null File: %s Line %in", __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仍然有一个有效的值,因为它不会知道释放的内存,但如果您访问它,它可能会导致分段错误。

正确的处理方法是:

  • 复制结果
  • 让调用者也传递一个语句对象,并在使用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);