【问题标题】:MySQL createStatement() memory leakMySQL createStatement() 内存泄漏
【发布时间】:2016-01-09 13:26:49
【问题描述】:

我正在运行具有大量 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。

【问题讨论】:

    标签: c++ mysql memory-leaks


    【解决方案1】:

    你错过了delete stmt。最好使用std::unique_ptr&lt;sql::Statement&gt;

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

    试试

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

    【讨论】:

    • 好点 - 指针仍然存在 - 当然智能指针是要走的路。我试过std::unique_ptr&lt;sql::Statement&gt; stmt = std::move(connection-&gt;createStatement()) ,但还是不行……你能帮忙吗?
    猜你喜欢
    • 2023-03-17
    • 1970-01-01
    • 2011-11-05
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-25
    相关资源
    最近更新 更多