python / cpython

The Python programming language
https://www.python.org
Other
63.53k stars 30.44k forks source link

Memory leak in gdbmmodule #62604

Closed f0d513f8-bc73-483a-a52c-978a34f853aa closed 11 years ago

f0d513f8-bc73-483a-a52c-978a34f853aa commented 11 years ago
BPO 18404
Nosy @jcea, @vstinner, @tiran
Files
  • gdbm-len-leak-fix.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields: ```python assignee = None closed_at = created_at = labels = ['extension-modules', 'performance'] title = 'Memory leak in gdbmmodule' updated_at = user = 'https://bugs.python.org/bkabrda' ``` bugs.python.org fields: ```python activity = actor = 'christian.heimes' assignee = 'none' closed = True closed_date = closer = 'christian.heimes' components = ['Extension Modules'] creation = creator = 'bkabrda' dependencies = [] files = ['30862'] hgrepos = [] issue_num = 18404 keywords = ['patch'] message_count = 3.0 messages = ['192647', '192723', '201218'] nosy_count = 4.0 nosy_names = ['jcea', 'vstinner', 'christian.heimes', 'bkabrda'] pr_nums = [] priority = 'normal' resolution = 'out of date' stage = 'resolved' status = 'closed' superseder = None type = 'resource usage' url = 'https://bugs.python.org/issue18404' versions = ['Python 3.3', 'Python 3.4'] ```

    f0d513f8-bc73-483a-a52c-978a34f853aa commented 11 years ago

    Function dbm_length from Modules/_gdbmmodule.c seems to be leaking memory. A simple reproducer:

    import dbm
    
    d = dbm.open('spam', 'c')
    d['x'] = '1'
    print(len(d))

    The interesting part of valgrind output with --leak-check=full:

    ==3312== 1 bytes in 1 blocks are definitely lost in loss record 1 of 3,622 ==3312== at 0x4A06409: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==3312== by 0x3A31A0349D: get_next_key (gdbmseq.c:72) ==3312== by 0x3A31A03595: gdbm_nextkey (gdbmseq.c:126) ==3312== by 0xDD74192: dbm_length (_gdbmmodule.c:104) ==3312== by 0x3A2473F50B: builtin_len (bltinmodule.c:1293) ==3312== by 0x3A247510D1: PyEval_EvalFrameEx (ceval.c:4080) ==3312== by 0x3A24753758: PyEval_EvalCodeEx (ceval.c:3462) ==3312== by 0x3A2475390A: PyEval_EvalCode (ceval.c:791) ==3312== by 0x3A24773893: run_mod (pythonrun.c:1989) ==3312== by 0x3A24775EE7: PyRun_FileExFlags (pythonrun.c:1945) ==3312== by 0x3A24777000: PyRun_SimpleFileExFlags (pythonrun.c:1455) ==3312== by 0x3A2478F72B: Py_Main (main.c:306)

    It seems that the problem is in the loop here [1] - specifically, the last okey.dptr seems not to be freed (the loop is terminated when key.dptr is NULL, but okey.dptr is still pointing to something). I'm attaching a supersimple patch that should fix this (unless I'm totally wrong about everything...)

    [1] http://hg.python.org/cpython/file/65f2c92ed079/Modules/_gdbmmodule.c#l102

    f0d513f8-bc73-483a-a52c-978a34f853aa commented 11 years ago

    I just tried rebuilding with my patch and running test suite + I did some manual testing and everything seems to work fine - and the memory leak is not there.

    tiran commented 11 years ago

    The problem is already fixed in 3.3 and 3.4. Thank you nevertheless! :)