
Apa yang dilakukan sebagian besar programmer ketika mereka mengetahui bahwa program mereka membocorkan memori? Tidak ada, biarkan pengguna membeli lebih banyak RAM.Saya berani berasumsi bahwa mereka menggunakan alat yang telah teruji oleh waktu seperti valgrind atau libasan, menjalankan dan menonton laporan. Biasanya dikatakan bahwa objek yang dibuat pada baris program ini dan itu tidak dirilis. Dan mengapa? Ini tidak ditulis di mana pun.
Posting ini berfokus pada pencari kebocoran yang paling banyak dibocorkan, konsep analisis statistik yang mendasari, dan bagaimana penerapannya.
Saya sudah menulis tentang bocor di habr, . - , . , . , , â . C++ vtbl . , . , , , valgrind , . topleaked , . , , â . , . " ", , , â . 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.