Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 30c9f39

Browse files
committed
Variety of small INC/DECREF patches that fix reported memory leaks
with free variables. Thanks to Martin v. Loewis for finding two of the problems. This fixes SF buf 405583. There is also a C API change: PyFrame_New() is reverting to its pre-2.1 signature. The change introduced by nested scopes was a mistake. XXX Is this okay between beta releases? cell_clear(), the GC helper, must decref its reference to break cycles. frame_dealloc() must dealloc all cell vars and free vars in addition to locals. eval_code2() setup code must INCREF cells it copies out of the closure. The STORE_DEREF opcode implementation must DECREF the object it passes to PyCell_Set().
1 parent 93fe96a commit 30c9f39

5 files changed

Lines changed: 13 additions & 12 deletions

File tree

Include/frameobject.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ extern DL_IMPORT(PyTypeObject) PyFrame_Type;
4646
#define PyFrame_Check(op) ((op)->ob_type == &PyFrame_Type)
4747

4848
DL_IMPORT(PyFrameObject *) PyFrame_New(PyThreadState *, PyCodeObject *,
49-
PyObject *, PyObject *,
50-
PyObject *);
49+
PyObject *, PyObject *);
5150

5251

5352
/* The rest of the interface is specific for frame objects */

Modules/pyexpat.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,6 @@ call_with_frame(PyCodeObject *c, PyObject* func, PyObject* args)
356356
c, /*code*/
357357
tstate->frame->f_globals, /*globals*/
358358
NULL /*locals*/
359-
#if PYTHON_API_VERSION >= 1010
360-
,NULL /*closure*/
361-
#endif
362359
);
363360
if (f == NULL)
364361
return NULL;

Objects/cellobject.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ cell_traverse(PyCellObject *op, visitproc visit, void *arg)
8383
static int
8484
cell_clear(PyCellObject *op)
8585
{
86+
Py_XDECREF(op->ob_ref);
8687
op->ob_ref = NULL;
8788
return 0;
8889
}

Objects/frameobject.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,14 @@ static PyFrameObject *free_list = NULL;
6565
static void
6666
frame_dealloc(PyFrameObject *f)
6767
{
68-
int i;
68+
int i, slots;
6969
PyObject **fastlocals;
7070

7171
Py_TRASHCAN_SAFE_BEGIN(f)
7272
/* Kill all local variables */
73+
slots = f->f_nlocals + f->f_ncells + f->f_nfreevars;
7374
fastlocals = f->f_localsplus;
74-
for (i = f->f_nlocals; --i >= 0; ++fastlocals) {
75+
for (i = slots; --i >= 0; ++fastlocals) {
7576
Py_XDECREF(*fastlocals);
7677
}
7778

@@ -108,7 +109,7 @@ PyTypeObject PyFrame_Type = {
108109

109110
PyFrameObject *
110111
PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
111-
PyObject *locals, PyObject *closure)
112+
PyObject *locals)
112113
{
113114
PyFrameObject *back = tstate->frame;
114115
static PyObject *builtin_object;

Python/ceval.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
430430

431431
f = PyFrame_New(tstate, /*back*/
432432
co, /*code*/
433-
globals, locals, closure);
433+
globals, locals);
434434
if (f == NULL)
435435
return NULL;
436436

@@ -578,8 +578,11 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
578578
}
579579
if (f->f_nfreevars) {
580580
int i;
581-
for (i = 0; i < f->f_nfreevars; ++i)
582-
freevars[f->f_ncells + i] = PyTuple_GET_ITEM(closure, i);
581+
for (i = 0; i < f->f_nfreevars; ++i) {
582+
PyObject *o = PyTuple_GET_ITEM(closure, i);
583+
Py_INCREF(o);
584+
freevars[f->f_ncells + i] = o;
585+
}
583586
}
584587

585588
if (tstate->sys_tracefunc != NULL) {
@@ -1662,14 +1665,14 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
16621665
err = -1;
16631666
break;
16641667
}
1665-
Py_INCREF(w);
16661668
PUSH(w);
16671669
break;
16681670

16691671
case STORE_DEREF:
16701672
w = POP();
16711673
x = freevars[oparg];
16721674
PyCell_Set(x, w);
1675+
Py_DECREF(w);
16731676
continue;
16741677

16751678
case BUILD_TUPLE:

0 commit comments

Comments
 (0)