mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
defdict_reduce(): Plug leaks.
We didn't notice these before because test_defaultdict didn't actually do anything before Georg fixed that earlier today. Neal's next refleak run then showed test_defaultdict leaking 9 references on each run. That's repaired by this checkin.
This commit is contained in:
parent
d17301f95c
commit
5566e96830
1 changed files with 11 additions and 10 deletions
|
@ -10,7 +10,7 @@
|
||||||
/* The block length may be set to any number over 1. Larger numbers
|
/* The block length may be set to any number over 1. Larger numbers
|
||||||
* reduce the number of calls to the memory allocator but take more
|
* reduce the number of calls to the memory allocator but take more
|
||||||
* memory. Ideally, BLOCKLEN should be set with an eye to the
|
* memory. Ideally, BLOCKLEN should be set with an eye to the
|
||||||
* length of a cache line.
|
* length of a cache line.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define BLOCKLEN 62
|
#define BLOCKLEN 62
|
||||||
|
@ -22,9 +22,9 @@
|
||||||
* element is at d.leftblock[leftindex] and its last element is at
|
* element is at d.leftblock[leftindex] and its last element is at
|
||||||
* d.rightblock[rightindex]; note that, unlike as for Python slice
|
* d.rightblock[rightindex]; note that, unlike as for Python slice
|
||||||
* indices, these indices are inclusive on both ends. By being inclusive
|
* indices, these indices are inclusive on both ends. By being inclusive
|
||||||
* on both ends, algorithms for left and right operations become
|
* on both ends, algorithms for left and right operations become
|
||||||
* symmetrical which simplifies the design.
|
* symmetrical which simplifies the design.
|
||||||
*
|
*
|
||||||
* The list of blocks is never empty, so d.leftblock and d.rightblock
|
* The list of blocks is never empty, so d.leftblock and d.rightblock
|
||||||
* are never equal to NULL.
|
* are never equal to NULL.
|
||||||
*
|
*
|
||||||
|
@ -37,11 +37,11 @@
|
||||||
* d.leftindex == CENTER+1; and d.rightindex == CENTER.
|
* d.leftindex == CENTER+1; and d.rightindex == CENTER.
|
||||||
* Checking for d.len == 0 is the intended way to see whether d is empty.
|
* Checking for d.len == 0 is the intended way to see whether d is empty.
|
||||||
*
|
*
|
||||||
* Whenever d.leftblock == d.rightblock,
|
* Whenever d.leftblock == d.rightblock,
|
||||||
* d.leftindex + d.len - 1 == d.rightindex.
|
* d.leftindex + d.len - 1 == d.rightindex.
|
||||||
*
|
*
|
||||||
* However, when d.leftblock != d.rightblock, d.leftindex and d.rightindex
|
* However, when d.leftblock != d.rightblock, d.leftindex and d.rightindex
|
||||||
* become indices into distinct blocks and either may be larger than the
|
* become indices into distinct blocks and either may be larger than the
|
||||||
* other.
|
* other.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -381,7 +381,7 @@ deque_remove(dequeobject *deque, PyObject *value)
|
||||||
int cmp = PyObject_RichCompareBool(item, value, Py_EQ);
|
int cmp = PyObject_RichCompareBool(item, value, Py_EQ);
|
||||||
|
|
||||||
if (deque->len != n) {
|
if (deque->len != n) {
|
||||||
PyErr_SetString(PyExc_IndexError,
|
PyErr_SetString(PyExc_IndexError,
|
||||||
"deque mutated during remove().");
|
"deque mutated during remove().");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -920,7 +920,7 @@ dequeiter_next(dequeiterobject *it)
|
||||||
"deque mutated during iteration");
|
"deque mutated during iteration");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
assert (!(it->b == it->deque->rightblock &&
|
assert (!(it->b == it->deque->rightblock &&
|
||||||
it->index > it->deque->rightindex));
|
it->index > it->deque->rightindex));
|
||||||
|
|
||||||
item = it->b->data[it->index];
|
item = it->b->data[it->index];
|
||||||
|
@ -1016,7 +1016,7 @@ dequereviter_next(dequeiterobject *it)
|
||||||
"deque mutated during iteration");
|
"deque mutated during iteration");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
assert (!(it->b == it->deque->leftblock &&
|
assert (!(it->b == it->deque->leftblock &&
|
||||||
it->index < it->deque->leftindex));
|
it->index < it->deque->leftindex));
|
||||||
|
|
||||||
item = it->b->data[it->index];
|
item = it->b->data[it->index];
|
||||||
|
@ -1117,7 +1117,7 @@ defdict_copy(defdictobject *dd)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
defdict_reduce(defdictobject *dd)
|
defdict_reduce(defdictobject *dd)
|
||||||
{
|
{
|
||||||
/* __reduce__ must returns a 5-tuple as follows:
|
/* __reduce__ must return a 5-tuple as follows:
|
||||||
|
|
||||||
- factory function
|
- factory function
|
||||||
- tuple of args for the factory function
|
- tuple of args for the factory function
|
||||||
|
@ -1155,6 +1155,7 @@ defdict_reduce(defdictobject *dd)
|
||||||
}
|
}
|
||||||
result = PyTuple_Pack(5, dd->dict.ob_type, args,
|
result = PyTuple_Pack(5, dd->dict.ob_type, args,
|
||||||
Py_None, Py_None, items);
|
Py_None, Py_None, items);
|
||||||
|
Py_DECREF(items);
|
||||||
Py_DECREF(args);
|
Py_DECREF(args);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue