【问题标题】:MySQL C++ Connector memory leaksMySQL C++ 连接器内存泄漏
【发布时间】:2020-04-18 21:34:57
【问题描述】:

我确实一直在浏览类似的帖子,但找不到适合我的问题的任何内容。

我正在尝试制作一个使用 MySQL 数据库进行查询的基本程序,一切正常,但我有很多内存泄漏。

#include <cppconn/driver.h>

#include <crtdbg.h>

int main() {

    {
        sql::Driver* driver = get_driver_instance();
    }

    _CrtDumpMemoryLeaks();
    return 0;
}

这是我正在使用的一个小sn-p。其余部分并不真正相关,因为我观察到即使是一小段代码也会产生大量内存泄漏,正如 _CrtDumpMemoryLeaks 调用所给出的那样。

我得到了 64 位版本并使用了动态链接库。我观察到我还需要单独链接boost库,所以我下载了它并把它的“包含”目录也放了。

我正在使用 Visual Studio 2019 社区。​​p>

任何帮助将不胜感激。干杯!

这是运行程序后的输出。

Detected memory leaks!
Dumping objects ->
{193} normal block at 0x0000014FB1F74710, 16 bytes long.
 Data: < F  O           > 90 46 FA B1 4F 01 00 00 00 00 00 00 00 00 00 00 
{192} normal block at 0x0000014FB1FA4670, 88 bytes long.
 Data: < (  O    (  O   > 00 28 F6 B1 4F 01 00 00 00 28 F6 B1 4F 01 00 00 
{191} normal block at 0x0000014FB1F8CC30, 24 bytes long.
 Data: <  g             > 18 03 67 C5 FE 7F 00 00 01 00 00 00 01 00 00 00 
{190} normal block at 0x0000014FB1F8C7B0, 24 bytes long.
 Data: <  d             > A8 96 64 C5 FE 7F 00 00 02 00 00 00 01 00 00 00 
{189} normal block at 0x0000014FB1F5E280, 104 bytes long.
 Data: <                > FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 
{188} normal block at 0x0000014FB1F57FE0, 168 bytes long.
 Data: <                > 00 00 00 00 D2 04 00 00 88 00 00 00 00 00 00 00 
{187} normal block at 0x0000014FB1F5F5A0, 104 bytes long.
 Data: <                > FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 
{186} normal block at 0x0000014FB1F61720, 56 bytes long.
 Data: <                > 00 00 00 00 D2 04 00 00 18 00 00 00 00 00 00 00 
{185} normal block at 0x0000014FB1F71050, 48 bytes long.
 Data: <                > 00 00 00 00 D2 04 00 00 10 00 00 00 00 00 00 00 
{184} normal block at 0x0000014FB1F70DB0, 40 bytes long.
 Data: <        p   O   > 00 00 00 00 CD CD CD CD 70 10 F7 B1 4F 01 00 00 
{183} normal block at 0x0000014FB1F70D40, 48 bytes long.
 Data: <                > 00 00 00 00 D2 04 00 00 10 00 00 00 00 00 00 00 
{182} normal block at 0x0000014FB1F710C0, 40 bytes long.
 Data: <        `   O   > 00 00 00 00 CD CD CD CD 60 0D F7 B1 4F 01 00 00 
{181} normal block at 0x0000014FB1F64C10, 80 bytes long.
 Data: <h i     dRi     > 68 C6 69 C5 FE 7F 00 00 64 52 69 C5 FE 7F 00 00 
{180} normal block at 0x0000014FB1F743F0, 16 bytes long.
 Data: <         L  O   > 01 00 00 00 00 00 00 00 10 4C F6 B1 4F 01 00 00 
{179} normal block at 0x0000014FB1F5BF60, 104 bytes long.
 Data: <                > FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 
{178} normal block at 0x0000014FB1F57280, 104 bytes long.
 Data: <                > FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 
{177} normal block at 0x0000014FB1F55310, 104 bytes long.
 Data: <                > FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 
{176} normal block at 0x0000014FB1F55560, 104 bytes long.
 Data: <                > FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 
{175} normal block at 0x0000014FB1F5E560, 104 bytes long.
 Data: <                > FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 
{174} normal block at 0x0000014FB1F55EE0, 104 bytes long.
 Data: <                > FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 
{173} normal block at 0x0000014FB1F57530, 104 bytes long.
 Data: <                > FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 
{172} normal block at 0x0000014FB1F57C50, 104 bytes long.
 Data: <                > FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 
{171} normal block at 0x0000014FB1F57960, 104 bytes long.
 Data: <                > FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 
{170} normal block at 0x0000014FB1F744E0, 8 bytes long.
 Data: <8 d     > 38 94 64 C5 FE 7F 00 00 
{169} normal block at 0x0000014FB1F62560, 24 bytes long.
 Data: <0 d      D  O   > 30 8C 64 C5 FE 7F 00 00 E0 44 F7 B1 4F 01 00 00 
{168} normal block at 0x0000014FB1F743A0, 16 bytes long.
 Data: <  f     `%  O   > F0 FE 66 C5 FE 7F 00 00 60 25 F6 B1 4F 01 00 00 
{167} normal block at 0x0000014FB1F62800, 88 bytes long.
 Data: <pF  O   pF  O   > 70 46 FA B1 4F 01 00 00 70 46 FA B1 4F 01 00 00 
{166} normal block at 0x0000014FB1F74850, 16 bytes long.
 Data: < s              > 98 73 E1 C5 FE 7F 00 00 00 00 00 00 00 00 00 00 
{162} normal block at 0x0000014FB1F65510, 80 bytes long.
 Data: < U  O    U  O   > 10 55 F6 B1 4F 01 00 00 10 55 F6 B1 4F 01 00 00 
{161} normal block at 0x0000014FB1F74F30, 16 bytes long.
 Data: <                > D8 D4 E1 C5 FE 7F 00 00 00 00 00 00 00 00 00 00 
{160} normal block at 0x0000014FB1F73080, 120 bytes long.
 Data: < 0  O    0  O   > 80 30 F7 B1 4F 01 00 00 80 30 F7 B1 4F 01 00 00 
{159} normal block at 0x0000014FB1F74D00, 16 bytes long.
 Data: <                > F0 D4 E1 C5 FE 7F 00 00 00 00 00 00 00 00 00 00 
{158} normal block at 0x0000014FB1F750C0, 16 bytes long.
 Data: <hs              > 68 73 E1 C5 FE 7F 00 00 00 00 00 00 00 00 00 00 
{157} normal block at 0x0000014FB1F72FE0, 88 bytes long.
 Data: < /  O    /  O   > E0 2F F7 B1 4F 01 00 00 E0 2F F7 B1 4F 01 00 00 
{156} normal block at 0x0000014FB1F74350, 16 bytes long.
 Data: < X              > 00 58 E1 C5 FE 7F 00 00 00 00 00 00 00 00 00 00 
Object dump complete.

所以看起来很多东西都在泄漏,只是在 Driver 类上调用了那个方法。析构函数是受保护的,所以我不能对它调用“delete”。

【问题讨论】:

  • 你怎么知道的?输出是什么?泄漏,如果有一些字节没有问题,当你分配一些兆字节并且不能释放它们时,这就会有问题。但即便如此,你也可以强迫所有记忆变得愚蠢。
  • 请记住,当main 返回时,内存中仍然保留着全局和静态对象。如果全局/静态对象没有机会自行清理,您对 _CrtDumpMemoryLeaks 的调用将毫无用处。您需要比在main 中调用更智能的方法来检测这样的内存泄漏。

标签: c++ mysql memory-leaks


【解决方案1】:

这并不是真正的内存泄漏,因为您“过早”检查。

Here你可以看到get_driver_instance是如何实现的:

static std::map< sql::SQLString, boost::shared_ptr<MySQL_Driver> > driver;

CPPCONN_PUBLIC_FUNC sql::mysql::MySQL_Driver * get_driver_instance()
{
    return get_driver_instance_by_name("");
}


CPPCONN_PUBLIC_FUNC sql::mysql::MySQL_Driver * get_driver_instance_by_name(const char * const clientlib)
{
    ::sql::SQLString dummy(clientlib);

    std::map< sql::SQLString, boost::shared_ptr< MySQL_Driver > >::const_iterator cit;

    if ((cit = driver.find(dummy)) != driver.end()) {
        return cit->second.get();
    } else {
        boost::shared_ptr< MySQL_Driver > newDriver;

        newDriver.reset(new MySQL_Driver(dummy));
        driver[dummy] = newDriver;

        return newDriver.get();
    }
}

您可以看到创建了一个全局变量driver,它是shared_ptrs 到各个MySQL_Driver 对象的映射。 get_driver_instance 只需调用 get_driver_instance_by_name(""),它将返回驱动程序 driver[""],如果它不存在则创建它。

shared_ptr documentation 中,您可以看到shared_ptrdeleteshared_ptr 本身被破坏时分配给它的指针。它会在映射driver 被破坏时被破坏,这将在您的进程被拆除时发生 - 之后 main 返回。

因此,在main 内,驱动程序仍然存在(析构函数尚未运行),因此_CrtDumpMemoryLeaks(); 将报告为虚假泄漏。

这基本上是here描述的问题。

我不确定是否有可靠的方法在析构函数之后运行代码,因为全局析构函数和 atexit 处理程序的运行顺序未在不同的翻译单元中指定。

由于您在 Windows 上,一个想法是(ab)使用线程本地存储回调,您可以在 DLL_THREAD_DETACH 步骤运行代码,据我所知,该步骤应该运行 em> 常规析构函数等。见this article。 (虽然我不确定,所以如果有人能发表评论,比我更了解这一点,我会很高兴!)

【讨论】:

  • 这实际上是有道理的......不知道这就是幕后发生的事情。使用 valgrind 会让我有更好的机会寻找泄漏吗?
  • 是的,因为它比较了所有分配和释放,也在main之前/之后。
  • 谢谢!现在必须弄清楚如何在没有 VS 的情况下链接所有内容,那也应该很有趣。
猜你喜欢
  • 1970-01-01
  • 2020-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-01
  • 2023-03-17
相关资源
最近更新 更多