summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2000-04-21 21:17:39 (GMT)
committerGuido van Rossum <guido@python.org>2000-04-21 21:17:39 (GMT)
commit25826c93c4cf1fcac537e6cded5ce986c751134e (patch)
tree58061e8b687c1fbb76c77d1926884d053550c8b4
parent5ce78f8e4e2522ab59f4c2c35a5a784dcc2dafc8 (diff)
downloadcpython-25826c93c4cf1fcac537e6cded5ce986c751134e.zip
cpython-25826c93c4cf1fcac537e6cded5ce986c751134e.tar.gz
cpython-25826c93c4cf1fcac537e6cded5ce986c751134e.tar.bz2
Charles Waldman writes:
""" Running "test_extcall" repeatedly results in memory leaks. One of these can't be fixed (at least not easily!), it happens since this code: def saboteur(**kw): kw['x'] = locals() d = {} saboteur(a=1, **d) creates a circular reference - d['x']['d']==d The others are due to some missing decrefs in ceval.c, fixed by the patch attached below. Note: I originally wrote this without the "goto", just adding the missing decref's where needed. But I think the goto is justified in keeping the executable code size of ceval as small as possible. """ [I think the circular reference is more like kw['x']['kw'] == kw. --GvR]
-rw-r--r--Python/ceval.c27
1 files changed, 13 insertions, 14 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 989e17f..d0958bd 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1623,8 +1623,7 @@ eval_code2(co, globals, locals,
if (!PyDict_Check(kwdict)) {
PyErr_SetString(PyExc_TypeError,
"** argument must be a dictionary");
- x = NULL;
- break;
+ goto extcall_fail;
}
}
if (flags & 1) {
@@ -1632,39 +1631,34 @@ eval_code2(co, globals, locals,
if (!PySequence_Check(stararg)) {
PyErr_SetString(PyExc_TypeError,
"* argument must be a sequence");
- x = NULL;
- break;
+ goto extcall_fail;
}
/* Convert abstract sequence to concrete tuple */
if (!PyTuple_Check(stararg)) {
PyObject *t = NULL;
t = PySequence_Tuple(stararg);
if (t == NULL) {
- x = NULL;
- break;
+ goto extcall_fail;
}
Py_DECREF(stararg);
stararg = t;
}
nstar = PyTuple_GET_SIZE(stararg);
if (nstar < 0) {
- x = NULL;
- break;
+ goto extcall_fail;
}
}
if (nk > 0) {
if (kwdict == NULL) {
kwdict = PyDict_New();
if (kwdict == NULL) {
- x = NULL;
- break;
+ goto extcall_fail;
}
}
else {
PyObject *d = PyDict_Copy(kwdict);
if (d == NULL) {
- x = NULL;
- break;
+ goto extcall_fail;
}
Py_DECREF(kwdict);
kwdict = d;
@@ -1680,7 +1674,7 @@ eval_code2(co, globals, locals,
PyString_AsString(key));
Py_DECREF(key);
Py_DECREF(value);
- break;
+ goto extcall_fail;
}
err = PyDict_SetItem(kwdict, key, value);
Py_DECREF(key);
@@ -1689,7 +1683,11 @@ eval_code2(co, globals, locals,
break;
}
if (err) {
- Py_DECREF(kwdict);
+ extcall_fail:
+ Py_XDECREF(kwdict);
+ Py_XDECREF(stararg);
+ Py_DECREF(func);
+ x=NULL;
break;
}
}
@@ -2382,6 +2380,7 @@ PyEval_CallObjectWithKeywords(func, arg, kw)
if (kw != NULL && !PyDict_Check(kw)) {
PyErr_SetString(PyExc_TypeError,
"keyword list must be a dictionary");
+ Py_DECREF(arg);
return NULL;
}