大多数程序员在发现自己的程序正在泄漏内存时会做什么? 没什么,让用户购买更多的RAM。我敢于假设他们采用了经过时间考验的可靠工具,例如valgrind或libasan,可以运行并观看报告。通常说,在这样的文件的程序行中创建的对象没有被释放。又为什么呢 这不是写在任何地方。
这篇文章重点介绍了无用的泄漏查找器,基本的统计分析概念以及如何应用它。
我已经写过关于哈勃尔神魂颠倒的文章,但我仍将在总体上重复主要思想。如果某些对象未释放,则它们将累积在内存中。这意味着我们有许多同类的,相似的序列。如果泄漏量超过实际使用量,则其中最常见的是泄漏物体的一部分。通常,C ++程序包含指向vtbl类的指针。这样我们可以找出忘记释放的对象的类型。显然,顶部包含大量垃圾,经常遇到的行,并且相同的valgrind会告诉我们什么以及在哪里流动更好。但是topleaked最初并不是为了与多年来制定的技术竞争而创建的。它被认为是解决其他问题无法解决的问题的工具-无法再现的泄漏分析。如果在测试环境中无法重现该问题,那么任何动态分析都是没有用的。如果错误仅在“战斗中”发生,甚至不稳定,那么我们可以获得的最大值是日志和内存转储。可以分析此转储。
C++ , - abort()
#include <iostream>
#include <assert.h>
#include <unistd.h>
class A {
size_t val = 12345678910;
virtual ~A(){}
};
int main() {
for (size_t i =0; i < 1000000; i++) {
new A();
}
std::cout << getpid() << std::endl;
abort();
}
topleaked
./toleaked leak.core
— .
0x0000000000000000 : 1050347
0x0000000000000021 : 1000003
0x00000002dfdc1c3e : 1000000
0x0000558087922d90 : 1000000
0x0000000000000002 : 198
0x0000000000000001 : 180
0x00007f4247c6a000 : 164
0x0000000000000008 : 160
0x00007f4247c5c438 : 153
0xffffffffffffffff : 141
, 0x2dfdc1c3e, 12345678910, . , . , , gdb gdb . -ogdb — , gdb.
$ ./topleaked -n10 -ogdb /home/core/leak.1002.core | gdb leak /home/core/leak.1002.core
...< gdb >
#0 0x00007f424784e6f4 in __GI___nanosleep (requested_time=requested_time@entry=0x7ffcfffedb50, remaining=remaining@entry=0x7ffcfffedb50) at ../sysdeps/unix/sysv/linux/nanosleep.c:28
28 ../sysdeps/unix/sysv/linux/nanosleep.c: No such file or directory.
(gdb) $1 = 1050347
(gdb) 0x0: Cannot access memory at address 0x0
(gdb) No symbol matches 0x0000000000000000.
(gdb) $2 = 1000003
(gdb) 0x21: Cannot access memory at address 0x21
(gdb) No symbol matches 0x0000000000000021.
(gdb) $3 = 1000000
(gdb) 0x2dfdc1c3e: Cannot access memory at address 0x2dfdc1c3e
(gdb) No symbol matches 0x00000002dfdc1c3e.
(gdb) $4 = 1000000
(gdb) 0x558087922d90 <_ZTV1A+16>: 0x87721bfa
(gdb) vtable for A + 16 in section .data.rel.ro of /home/g.smorkalov/dlang/topleaked/leak
(gdb) $5 = 198
(gdb) 0x2: Cannot access memory at address 0x2
(gdb) No symbol matches 0x0000000000000002.
(gdb) $6 = 180
(gdb) 0x1: Cannot access memory at address 0x1
(gdb) No symbol matches 0x0000000000000001.
(gdb) $7 = 164
(gdb) 0x7f4247c6a000: 0x47ae6000
(gdb) No symbol matches 0x00007f4247c6a000.
(gdb) $8 = 160
(gdb) 0x8: Cannot access memory at address 0x8
(gdb) No symbol matches 0x0000000000000008.
(gdb) $9 = 153
(gdb) 0x7f4247c5c438 <_ZTVN10__cxxabiv120__si_class_type_infoE+16>: 0x47b79660
(gdb) vtable for __cxxabiv1::__si_class_type_info + 16 in section .data.rel.ro of /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) $10 = 141
(gdb) 0xffffffffffffffff: Cannot access memory at address 0xffffffffffffffff
(gdb) No symbol matches 0xffffffffffffffff.
(gdb) quit
, . $4 = 1000000 . x info symbol . , vtable for A, A.
. , , 15. , .
, ?
— ? , , . topleaked . , , , . ? , , . , , .
…
. , . — . 3 . , . 3 , - . , 2-3 — . . , — , . C++ . , . C, D, Rust, Go NodeJS. , js .
. , , , , close. , . ( ), , fd (512000 ) . . . , , .
topleaked — . , , . , , . : . state — enum, . : , , websocket, . , , .
. Topleaked , , 8 8- . - , , , - . - , . , vtbl, . , , “ ”. vtbl - state. , . .
C++ — ABI - . POD trivial C. , , . . , linux gcc , vtbl — . offsetof(state) . :
struct Base {
virtual void foo() = 0;
};
struct Der : Base {
size_t a = 15;
void foo() override {
}
};
int main()
{
for (size_t i = 0; i < 10000; ++i) {
new Der;
}
auto d = new Der;
cout << offsetof(Der, a) << endl;
abort();
return 0;
}
offsetof Der::a, “” 10000 . topleaked
topleaked my_core.core
0x0000000000000000 : 50124
0x000000000000000f : 10005
0x0000000000000021 : 10004
0x000055697c45cd78 : 10002
0x0000000000000002 : 195
0x0000000000000001 : 182
0x00007fe9cbd6c000 : 167
0x0000000000000008 : 161
0x00007fe9cbd5e438 : 154
0x0000000000001000 : 112
0x000055697c45cd78 vtbl Der. offsetof 8. , 8 . topleaked — . -f , , --memberOffset — -f, --memberType — . uint8, uint16, uint32 uint64.
topleaked my_core.core -f0x55697c45cd78 --memberOffset=8 --memberType=uint64
:
0x000000000000000f : 10001
0x000055697ccaa080 : 1
10000 0x0f, , .
Happy End
. , , , . , . , . , , . , TCP, — websocket upgrade, - . . — , . , (, ) TCP. , , . . , , — TCP Keep Alive. https://blog.cloudflare.com/when-tcp-sockets-refuse-to-die/
, . , . websocket . , .
D
readFile(name, offset, limit)
.findMember!uint64_t(pattern, memberOffset)
.findMostFrequent(size).printResult(format);
findMember — , , findMostFrequent — , . (ranges) . , , , .
P.S. Crazy Panda , . , topleaked.