在下面的C++ 17程序中,不同的静态分析器在关闭和打开数据库时显示内存泄漏。
我写了一个最小的可重复的例子,显示了实际代码似乎泄漏的部分。
更改SQL驱动程序似乎减少了内存泄漏检测,但仍然存在一些问题。
下面是内存泄漏报告的示例:
main.cpp
#include <mcheck.h>
#include <iostream>
#include <memory>
#include <QSqlDatabase>
auto getDb() -> QSqlDatabase {
QSqlDatabase db = QSqlDatabase::addDatabase("QOCI");
db.setDatabaseName("db");
db.setHostName("123.456.789");
db.setUserName("userName");
db.setPassword("password");
db.setPort(1234);
db.setConnectOptions("OCI_ATTR_PREFETCH_ROWS=100;OCI_ATTR_PREFETCH_MEMORY=0");
return db;
}
auto main(int argc, char** argv) -> int {
if (argc != 4) {
std::cerr << "Usage: " << argv[0] << " ITERATIONS WITH_TRACE USE_FIX" << std::endl;
return EXIT_FAILURE;
}
const long ITERATIONS = std::strtol(argv[1], nullptr, 10);
const bool TRACE = std::strtol(argv[2], nullptr, 10) == 1;
const bool USE_FIX = std::strtol(argv[3], nullptr, 10) == 1;
QSqlDatabase db = getDb();
std::cout << "Running test loop of " << ITERATIONS << " iterations ...\n" << std::endl;
if (TRACE) {
std::cout << "start mtrace" << std::endl;
mtrace();
}
for (int i = 0; i < ITERATIONS; ++i) {
if (i % 100 == 0) { std::cout << "i=" << i << std::endl; }
// Refresh the connection
if (db.isOpen()) {
db.close();
// Possible fix
if (USE_FIX) {
QSqlDatabase::removeDatabase("db");
db = getDb();
}
}
db.open();
// End refresh
}
if (TRACE) { muntrace(); }
QSqlDatabase::removeDatabase("db");
return EXIT_SUCCESS;
}
记忆博士
~~Dr.M~~ Error #829: UNADDRESSABLE ACCESS: reading 0xffffffffff5ff080-0xffffffffff5ff084 4 byte(s)
~~Dr.M~~ # 0 linux-vdso.so.1!? +0x0 (0x00007ffc4f452bcf <linux-vdso.so.1+0xbcf>)
~~Dr.M~~ # 1 libclntshcore.so.12.1!sLdiGetDate
~~Dr.M~~ # 2 libclntsh.so.12.1!dbglWriteLogCommon
~~Dr.M~~ # 3 libclntsh.so.12.1!dbgrlWriteAlertDetail
~~Dr.M~~ # 4 libclntsh.so.12.1!dbgrlWriteAlertText
~~Dr.M~~ # 5 libclntsh.so.12.1!nlddwrtlog
~~Dr.M~~ # 6 libclntsh.so.12.1!nldsadrvfp
~~Dr.M~~ # 7 libclntsh.so.12.1!nldsfprintf
~~Dr.M~~ # 8 libclntsh.so.12.1!niqlce1
~~Dr.M~~ # 9 libclntsh.so.12.1!niotns
~~Dr.M~~ #10 libclntsh.so.12.1!osncon
~~Dr.M~~ #11 libclntsh.so.12.1!kpuadef
~~Dr.M~~ #12 libclntsh.so.12.1!upiini
~~Dr.M~~ #13 libclntsh.so.12.1!kpuatch
~~Dr.M~~ #14 libclntsh.so.12.1!OCIServerAttach
~~Dr.M~~ #15 libqsqloci.so!_init +0x4e16 (0x00007fd42669b12f <libqsqloci.so+0xb12f>)
~~Dr.M~~ #16 libQt5Sql.so.5!QSqlDatabase::open +0x30 (0x00007fd428db3ce1 <libQt5Sql.so.5+0x14ce1>)
~~Dr.M~~ #17 main [/opt/select/gitlab-runner/francelis/frlis_DbCore/src/MemoryLeakTest.cpp:56]
...
~~Dr.M~~ ERRORS FOUND:
~~Dr.M~~ 101 unique, 578 total unaddressable access(es)
~~Dr.M~~ 759 unique, 5364 total uninitialized access(es)
~~Dr.M~~ 0 unique, 0 total invalid heap argument(s)
~~Dr.M~~ 4 unique, 8 total warning(s)
~~Dr.M~~ 2 unique, 2 total, 41616 byte(s) of leak(s)
~~Dr.M~~ 1 unique, 1 total, 139648 byte(s) of possible leak(s)
~~Dr.M~~ ERRORS IGNORED:
~~Dr.M~~ 328 unique, 552 total, 854604 byte(s) of still-reachable allocation(s)
~~Dr.M~~ (re-run with "-show_reachable" for details)
mtrace
= Start
@ /opt/Qt5/lib/libQt5Core.so.5:(_ZN10QArrayData8allocateEmmm6QFlagsINS_16AllocationOptionEE+0x59)[0x7fa2d5f16fe9] + 0xbb8f20 0x4e
@ /opt/Qt5/lib/libQt5Core.so.5:(_ZN9QListData11detach_growEPii+0x45)[0x7fa2d5f643a5] + 0xbb90b0 0x20
@ /opt/Qt5/lib/libQt5Core.so.5:(_ZN10QArrayData8allocateEmmm6QFlagsINS_16AllocationOptionEE+0x59)[0x7fa2d5f16fe9] + 0xbb9020 0x4e
@ /opt/Qt5/lib/libQt5Core.so.5:(_ZN10QArrayData8allocateEmmm6QFlagsINS_16AllocationOptionEE+0x59)[0x7fa2d5f16fe9] + 0xbb8fd0 0x46
@ /opt/Qt5/lib/libQt5Core.so.5:(_ZN10QArrayData8allocateEmmm6QFlagsINS_16AllocationOptionEE+0x59)[0x7fa2d5f16fe9] + 0xbb8ef0 0x20
@ /opt/Qt5/plugins/sqldrivers/libqsqloci.so:[0x7fa2d6489c3f] - 0xbb8ef0
@ /opt/Qt5/plugins/sqldrivers/libqsqloci.so:[0x7fa2d6489c47] - 0xbb8fd0
...
@ /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1:(nlnvmal+0x1a)[0x7fa2d32d9fda] + 0xbded30 0x38
@ /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1:(nlnvmal+0x1a)[0x7fa2d32d9fda] + 0xbded70 0x5
@ /lib64/ld-linux-x86-64.so.2:[0x7fa2d643b16e] + 0xbe2b10 0x90
@ /lib64/libc.so.6:(__strdup+0x1a)[0x7fa2d506cb8a] + 0xbe2bb0 0x28
@ /lib64/libnss_myhostname.so.2:(_nss_myhostname_gethostbyname4_r+0x1e3)[0x7fa2c6a032b3] - 0xbe2bb0
@ /lib64/libc.so.6:(__resolv_context_put+0x45)[0x7fa2d50f08f5] - 0xbdf320
@ /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1:[0x7fa2d32d948d] - 0xbdf300
...
= End
...
Valgrind
==649== Memcheck, a memory error detector
==649== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==649== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==649== Command: bin/MemoryLeakTest 1 0
==649==
==649== Conditional jump or move depends on uninitialised value(s)
==649== at 0xB3AC860: lmmmalloc (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB18EEC5: lmmcis (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB194589: lpmpali (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB19413C: lpmloadpkg (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB17609A: lfvLoadPkg (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB175D45: lfvSetShlMode (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB17573F: lfvini1 (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB175384: lfvinit (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0x7FB1768: kpummpin (in /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1)
==649== by 0x7A3C6A3: kpuenvcr (in /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1)
==649== by 0x79F370E: OCIEnvCreate (in /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1)
==649== by 0x41DDF90: ??? (in /opt/Qt5/plugins/sqldrivers/libqsqloci.so)
==649==
==649== Conditional jump or move depends on uninitialised value(s)
==649== at 0xB3AC88F: lmmmalloc (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB18EF8B: lmmcis (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB194589: lpmpali (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB19413C: lpmloadpkg (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB17609A: lfvLoadPkg (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB175D45: lfvSetShlMode (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB17573F: lfvini1 (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB175384: lfvinit (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0x7FB1768: kpummpin (in /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1)
==649== by 0x7A3C6A3: kpuenvcr (in /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1)
==649== by 0x79F370E: OCIEnvCreate (in /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1)
==649== by 0x41DDF90: ??? (in /opt/Qt5/plugins/sqldrivers/libqsqloci.so)
==649==
==649== Use of uninitialised value of size 8
==649== at 0xB114130: lxgt2u (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB3A0F47: lxgcnvb (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB3996B0: lxgcnv (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0x87FD6CA: kpuecs2u (in /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1)
==649== by 0xA33AADC: OCIErrorGet (in /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1)
==649== by 0x41DB993: ??? (in /opt/Qt5/plugins/sqldrivers/libqsqloci.so)
==649== by 0x41DC0EF: ??? (in /opt/Qt5/plugins/sqldrivers/libqsqloci.so)
==649== by 0x41DF071: ??? (in /opt/Qt5/plugins/sqldrivers/libqsqloci.so)
==649== by 0x4041CE0: QSqlDatabase::open() (in /opt/Qt5/lib/libQt5Sql.so.5.10.1)
==649== by 0x402C8E: main (MemoryLeakTest.cpp:56)
==649==
==649== Conditional jump or move depends on uninitialised value(s)
==649== at 0xB1141AD: lxgt2u (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB3A0F47: lxgcnvb (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0xB3996B0: lxgcnv (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0x87FD6CA: kpuecs2u (in /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1)
==649== by 0xA33AADC: OCIErrorGet (in /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1)
==649== by 0x41DB993: ??? (in /opt/Qt5/plugins/sqldrivers/libqsqloci.so)
==649== by 0x41DC0EF: ??? (in /opt/Qt5/plugins/sqldrivers/libqsqloci.so)
==649== by 0x41DF071: ??? (in /opt/Qt5/plugins/sqldrivers/libqsqloci.so)
==649== by 0x4041CE0: QSqlDatabase::open() (in /opt/Qt5/lib/libQt5Sql.so.5.10.1)
==649== by 0x402C8E: main (MemoryLeakTest.cpp:56)
==649==
==649== Conditional jump or move depends on uninitialised value(s)
==649== at 0x8604854: __intel_sse2_strncpy (in /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1)
==649== by 0xB176387: lfvpkgname (in /usr/lib/oracle/12.2/client64/lib/libclntshcore.so.12.1)
==649== by 0x7FB1795: kpummpin (in /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1)
==649== by 0x7A3C6A3: kpuenvcr (in /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1)
==649== by 0x79F370E: OCIEnvCreate (in /usr/lib/oracle/12.2/client64/lib/libclntsh.so.12.1)
==649== by 0x41DDF90: ??? (in /opt/Qt5/plugins/sqldrivers/libqsqloci.so)
==649== by 0x41E8712: ??? (in /opt/Qt5/plugins/sqldrivers/libqsqloci.so)
==649== by 0x4043851: ??? (in /opt/Qt5/lib/libQt5Sql.so.5.10.1)
==649== by 0x4043D60: QSqlDatabase::addDatabase(QString const&, QString const&) (in /opt/Qt5/lib/libQt5Sql.so.5.10.1)
==649== by 0x4027E8: main (MemoryLeakTest.cpp:28)
...
==649== LEAK SUMMARY:
==649== definitely lost: 128 bytes in 2 blocks
==649== indirectly lost: 41,488 bytes in 8 blocks
==649== possibly lost: 139,648 bytes in 3 blocks
==649== still reachable: 763,863 bytes in 332 blocks
==649== suppressed: 0 bytes in 0 blocks
==649== Reachable blocks (those to which a pointer was found) are not shown.
==649== To see them, rerun with: --leak-check=full --show-leak-kinds=all
即使使用USE_FIX
,也会显示内存错误。如何消除这些错误?
1条答案
按热度按时间rfbsl7qr1#
用pmap命令监控程序进程后,
在运行程序的docker容器中,在10 k次迭代中使用的内存保持不变,所以我假设这个程序实际上不会泄漏。* (我们未能针对主代码的泄漏部分)*
由于@ibre5041的评论,所有静态分析器的内存泄漏报告都愿意成为误报,因为Oracle的OCI库是构建的。