MySQL createStatement()内存泄漏

时间:2016-01-09 13:26:49

标签: c++ mysql memory-leaks

我正在运行一个包含大量MYSQL数据库访问权限的大代码,我注意到内存泄漏会在运行一天后占用整个服务器内存。

通过隔离片断,我最终得到以下测试代码:

#include <iostream>
#include <string>
#include <sstream>
#include <thread>
#include <chrono>


#include "mysql_connection.h"

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

int main() {

    try
    {
        sql::Driver *driver = NULL;
        sql::Connection *connection = NULL;

        driver = get_driver_instance();

        connection = driver->connect("tcp://127.0.0.1:3306", "user", "pass");
        connection->setSchema("myschema");
        connection->setAutoCommit(true);

        while (true)
        {
            std::string sql("INSERT INTO tablename ('field1', 'field2', 'field3') VALUES ('1', '2', '3')");
            sql::Statement *stmt;
            stmt = connection->createStatement();
            stmt->execute(sql.c_str());
            stmt->close();
            std::cout << sql << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
    catch (std::exception& ex)
    {
        std::cout << "Error occurred: " << std::endl;
        std::cout << ex.what() << std::endl;
    }
    catch(...)
    {
        std::cout << "Unknown failure occurred." << std::endl;
    }
}

当主while运行时,进程内存使用量开始增加,如每分钟1Mb。

使用valgrid --leak-check=full我在点击退出主循环后获得了以下结果:

==11988== Process terminating with default action of signal 2 (SIGINT)
==11988==    at 0x57F5D6D: recv (recv.c:29)
==11988==    by 0x5B1B022: vio_read (in /usr/lib/x86_64-linux-gnu/libmysqlclient.so.18.1.0)
==11988==    by 0x5B1B0A4: vio_read_buff (in /usr/lib/x86_64-linux-gnu/libmysqlclient.so.18.1.0)
==11988==    by 0x5AFA702: ??? (in /usr/lib/x86_64-linux-gnu/libmysqlclient.so.18.1.0)
==11988==    by 0x5AFA976: ??? (in /usr/lib/x86_64-linux-gnu/libmysqlclient.so.18.1.0)
==11988==    by 0x5AFB6A3: my_net_read (in /usr/lib/x86_64-linux-gnu/libmysqlclient.so.18.1.0)
==11988==    by 0x5AF151C: cli_safe_read (in /usr/lib/x86_64-linux-gnu/libmysqlclient.so.18.1.0)
==11988==    by 0x5AF2A15: ??? (in /usr/lib/x86_64-linux-gnu/libmysqlclient.so.18.1.0)
==11988==    by 0x5AF43A5: mysql_real_query (in /usr/lib/x86_64-linux-gnu/libmysqlclient.so.18.1.0)
==11988==    by 0x4F15BEE: sql::mysql::NativeAPI::LibmysqlStaticProxy::real_query(st_mysql*, char const*, unsigned long) (in /usr/lib/libmysqlcppconn.so.7.1.1.3)
==11988==    by 0x4F176F5: sql::mysql::NativeAPI::MySQL_NativeConnectionWrapper::query(sql::SQLString const&) (in /usr/lib/libmysqlcppconn.so.7.1.1.3)
==11988==    by 0x4F10579: sql::mysql::MySQL_Statement::do_query(sql::SQLString const&) (in /usr/lib/libmysqlcppconn.so.7.1.1.3)
==11988== 
==11988== HEAP SUMMARY:
==11988==     in use at exit: 333,479 bytes in 1,869 blocks
==11988==   total heap usage: 5,566 allocs, 3,697 frees, 1,100,674 bytes allocated
==11988== 
==11988== 144,880 bytes in 1,811 blocks are definitely lost in loss record 42 of 42
==11988==    at 0x4C2C12F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11988==    by 0x4EC4334: sql::mysql::MySQL_Connection::createStatement() (in /usr/lib/libmysqlcppconn.so.7.1.1.3)
==11988==    by 0x4011B7: main (test.cpp:32)
==11988== 
==11988== LEAK SUMMARY:
==11988==    definitely lost: 144,880 bytes in 1,811 blocks
==11988==    indirectly lost: 0 bytes in 0 blocks
==11988==      possibly lost: 0 bytes in 0 blocks
==11988==    still reachable: 188,599 bytes in 58 blocks
==11988==         suppressed: 0 bytes in 0 blocks
==11988== Reachable blocks (those to which a pointer was found) are not shown.
==11988== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==11988== 
==11988== For counts of detected and suppressed errors, rerun with: -v
==11988== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

那么,我做错了什么或者这是一个知道的MYSQL错误?如何修复代码和/或mySQL?

我在Ubuntu 15.10上运行MySql 5.6.27-0ubuntu1。

1 个答案:

答案 0 :(得分:2)

您错过了delete stmt。更好的方法是使用std::unique_ptr<sql::Statement>

(参见例如https://dev.mysql.com/doc/connector-cpp/en/connector-cpp-examples-query.html

尝试

std::unique_ptr<sql::Statement> stmt(connection->CreateStatement());