C++ MySQL C+中的内存泄漏+;连接器

C++ MySQL C+中的内存泄漏+;连接器,c++,mysql,mysql-connector,C++,Mysql,Mysql Connector,我使用MySQL C++连接器。Valgrind显示它在每个连接上都泄漏了192字节。 它只在线程化环境中泄漏内存,没有线程化。它没有泄漏任何内存。我做错了什么?我需要调用一些其他函数来进行清理吗? 示例代码: #include <pthread.h> #include <iostream> #include <cppconn/driver.h> #include <cppconn/exception.h> #include <cppconn

我使用MySQL C++连接器。Valgrind显示它在每个连接上都泄漏了192字节。 它只在线程化环境中泄漏内存,没有线程化。它没有泄漏任何内存。我做错了什么?我需要调用一些其他函数来进行清理吗? 示例代码:

#include <pthread.h>
#include <iostream>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>

using namespace std;

void* test(void* arg) {

  try {
    sql::Driver *driver;
    sql::Connection *con;
    /* Create a connection */
    driver = get_driver_instance();
    con = driver->connect("tcp://127.0.0.1:3306", "root", "root");
    /* Connect to the MySQL test database */
    con->setSchema("test");
    delete con;
  } catch (sql::SQLException &e) {
    cout << "# ERR: SQLException in " << __FILE__;
    cout << "(" << __FUNCTION__ << ") on line " << __LINE__ << endl;
    cout << "# ERR: " << e.what();
    cout << " (MySQL error code: " << e.getErrorCode();
    cout << ", SQLState: " << e.getSQLState() << " )" << endl;
  }
  return NULL;
}

int main() {
  pthread_t thread1, thread2, thread3, thread4;
  pthread_create(&thread1, NULL, test, NULL);
  pthread_create(&thread2, NULL, test, NULL);
  pthread_join(thread1, NULL);
  pthread_join(thread2, NULL);
  return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
无效*测试(无效*参数){
试一试{
sql::Driver*驱动程序;
连接*con;
/*创建连接*/
driver=get_driver_instance();
con=驱动程序->连接(“tcp://127.0.0.1:3306“,”根“,”根“);
/*连接到MySQL测试数据库*/
con->setSchema(“测试”);
删除con;
}捕获(sql::SQLException&e){

正如WhozCraig建议的那样,您可以在测试函数中添加
delete Driver;
,但我建议对MYSQL的所有内容使用
auto\u ptr
或C++11
unique\u ptr
shared\u ptr
,您永远不必担心内存泄漏

以此为例,

使用C++11

std::unique_ptr< sql::Connection > con( driver->connect("tcp://127.0.0.1:3306", "root", "root"));
这可能是你需要的


还有一个可能非常有用的方法,它与您的做法有点不同。第一个问题是您的代码是错误的。
try
块中出现任何异常时,程序将永远不会到达
delete con;
语句,您将与MySQL服务器保持打开的连接,并出现内存泄漏。您必须声明并删除elete
con
try
之外阻止或使用C++11智能指针:

错误:

  try {
    sql::Connection *con = driver->connect("URL", "user", "password");

    // code

    delete con;
  }
  catch (const sql::SQLException &e) {
    // code
  }
正确,在C++11之前:

  sql::Connection *con = NULL;     
  try {
    con = driver->connect("URL", "user", "password");

    // code

  }
  catch (const sql::SQLException &e) {
    // code
  }
  delete con; // delete on NULL is harmless.
  con = NULL;
  try {
    // unique_ptr will automatically call delete when it goes out of scope.
    // That will also happen in case of exception.
    std::unique_ptr<sql::Connection> con (driver->connect("URL", "user", "password"));     

    // code

  }
  catch (const sql::SQLException &e) {
    // code
  }
正确,C++11,推荐方式:

  sql::Connection *con = NULL;     
  try {
    con = driver->connect("URL", "user", "password");

    // code

  }
  catch (const sql::SQLException &e) {
    // code
  }
  delete con; // delete on NULL is harmless.
  con = NULL;
  try {
    // unique_ptr will automatically call delete when it goes out of scope.
    // That will also happen in case of exception.
    std::unique_ptr<sql::Connection> con (driver->connect("URL", "user", "password"));     

    // code

  }
  catch (const sql::SQLException &e) {
    // code
  }
试试看{
//unique_ptr在超出范围时将自动调用delete。
//在例外情况下也会发生这种情况。
std::unique_ptr con(驱动程序->连接(“URL”、“用户”、“密码”);
//代码
}
catch(constsql::SQLException&e){
//代码
}

另外,
driver=get\u driver\u instance();
应该在程序中只调用一次,而不是在每个线程中。因此,应该将
sql::driver*driver;
设置为全局变量,并在
main()中调用
driver=get\u driver\u instance();
在创建任何线程之前。

由于不了解mysql,valgrind与您的代码相关的转储表明泄漏是驱动程序实例,但这有可能被隐藏在TLS中并用于缓存。我很想看看循环中的代码会发生什么(即每个线程调用10次)这对你来说是微不足道的。@WhozCraig如何释放驱动程序的内存。它的析构函数是私有的?@VivekGoel我面临着同样的问题。你能提供详细的解决方法吗?除此之外,每当try…catch块发生异常时,你的程序就会泄漏,
驱动程序
使用错误。你需要有一个glo用于驱动程序的bal变量,只从
main()
调用一次
get\u driver\u instance()
。不要在
driver
上调用delete,也不要尝试以某种方式释放它,它是一个嵌入式结构,应该一直存在到程序退出为止。使用线程时,在每个新线程中都必须调用
driver->threadInit()
。线程使用完MySQL后,在线程终止之前,必须调用
驱动程序->线程结束();
。如果我试图删除驱动器对象,则会出现以下错误。虚拟sql::驱动程序::~driver()'是否受保护?我做了一些挖掘,我们在生产中使用了此功能。我们的代码中没有
delete driver
,但在文档和代码中有一个
con->close();
before
delete con
如果你只是为驱动程序添加解构器,它就解决了问题。我面临同样的问题,但无法得到你提供的解决方案。如何为驱动程序添加解构器有点让人困惑?你的意思是从驱动程序派生另一个类还是其他方法?
  try {
    // unique_ptr will automatically call delete when it goes out of scope.
    // That will also happen in case of exception.
    std::unique_ptr<sql::Connection> con (driver->connect("URL", "user", "password"));     

    // code

  }
  catch (const sql::SQLException &e) {
    // code
  }