Tracking a memory leak in C extension - interpreting the output of PYTHONMALLOCSTATS

Bartosz Golaszewski brgl at bgdev.pl
Mon Jul 23 14:02:13 EDT 2018


Hi!

A user recently reported a memory leak in python bindings (C extension
module) to a C library[1] I wrote. I've been trying to fix it since
but so far without success. Since I'm probably dealing with a space
leak rather than actual memory leak, valgrind didn't help much even
when using malloc as allocator. I'm now trying to use
PYTHONMALLOCSTATS but need some help on how to interpret the output
emitted it's enabled.

I'm setting PYTHONMALLOCSTATS=1 & PYTHONMALLOC=pymalloc_debug and then
running the script that triggers the leak. The last debug message is
as follows:

class   size   num pools   blocks in use  avail blocks
-----   ----   ---------   -------------  ------------
    3     32           1               2           124
    4     40           2               9           193
    5     48           1               3            81
    6     56           1               4            68
    7     64          11             295           398
    8     72           9             260           244
    9     80          36             831           969
   10     88          79            1542          2092
   11     96         131            3262          2240
   12    104          70            1903           757
   13    112          19             289           395
   14    120          11             139           224
   15    128           7              88           129
   16    136           6              70           104
   17    144           5              44            96
   18    152           4              47            57
   19    160          24             342           258
   20    168           4              17            79
   21    176          24             360           192
   22    184           2               8            36
   23    192           2              11            31
   24    200          22             227           213
   25    208           3              13            44
   26    216           3               7            47
   27    224           2              13            23
   28    232           2               6            28
   29    240           3               8            40
   30    248           2              10            22
   31    256           3              10            35
   32    264           2               9            21
   33    272           3              11            31
   34    280           2              10            18
   35    288           1               3            11
   36    296           2               9            17
   37    304           2               9            17
   38    312           2               5            19
   39    320           2               5            19
   40    328          14             105            63
   41    336           2               3            21
   42    344           1               3             8
   43    352           1               3             8
   44    360           2               3            19
   45    368           1               3             8
   46    376           1               1             9
   47    384           2               4            16
   48    392           2               6            14
   49    400           2               3            17
   50    408           1               1             8
   51    416           1               3             6
   52    424           2               4            14
   53    432       50967          458680            23
   54    440           3               9            18
   55    448           4              15            21
   56    456           4              12            20
   57    464           3               8            16
   58    472           2               5            11
   59    480           1               4             4
   60    488           1               3             5
   61    496           4              11            21
   62    504           4              13            19
   63    512           2               7             7

# times object malloc called       =            2,811,245
# arenas allocated total           =                  810
# arenas reclaimed                 =                    0
# arenas highwater mark            =                  810
# arenas allocated current         =                  810
810 arenas * 262144 bytes/arena    =          212,336,640

# bytes in allocated blocks        =          199,277,432
# bytes in available blocks        =            1,138,472
308 unused pools * 4096 bytes      =            1,261,568
# bytes lost to pool headers       =            2,473,536
# bytes lost to quantization       =            8,185,632
# bytes lost to arena alignment    =                    0
Total                              =          212,336,640

The number of pools in arena 53 continuously grows. Its size column
says: 432. I couldn't find any documentation on what it means but I
assume it's an allocation of 432 bytes. I launched gdb and set the
following breakpoint: 'b PyMem_Malloc if size == 432' but the
breakpoint was never triggered. I tried the same for PyObject_Malloc
and still nothing.

How do I use the info produced by PYTHONMALLOCSTATS do get to the
culprit of the leak? Is there anything wrong in my reasoning here?

Best regards,
Bartosz Golaszewski

[1] https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/


More information about the Python-list mailing list