8000 py: Clear allocated, but unused memory in containers. · lurch/micropython@a224067 · GitHub
[go: up one dir, main page]

Skip to content

Commit a224067

Browse files
committed
py: Clear allocated, but unused memory in containers.
Also, clear up freed slots in containers. As a follow up to 32bef31.
1 parent 7ce6a8f commit a224067

File tree

3 files changed

+9
-0
lines changed

3 files changed

+9
-0
lines changed

py/obj.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,3 +539,5 @@ bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, u
539539
bool mp_seq_cmp_objs(int op, const mp_obj_t *items1, uint len1, const mp_obj_t *items2, uint len2);
540540
mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp_obj_t *args);
541541
mp_obj_t mp_seq_count_obj(const mp_obj_t *items, uint len, mp_obj_t value);
542+
// Helper to clear stale pointers from allocated, but unused memory, to preclude GC problems
543+
#define mp_seq_clear(start, len, alloc_len, item_sz) memset((byte*)(start) + (len) * (item_sz), 0, ((alloc_len) - (len)) * (item_sz))

py/objarray.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) {
125125
// TODO: alloc policy
126126
self->free = 8;
127127
self->items = m_realloc(self->items, item_sz * self->len, item_sz * (self->len + self->free));
128+
mp_seq_clear(self->items, self->len + 1, self->len + self->free, item_sz);
128129
}
129130
mp_binary_set_val_array(self->typecode, self->items, self->len++, arg);
130131
self->free--;

py/objlist.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
163163
if (self->len >= self->alloc) {
164164
self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc * 2);
165165
self->alloc *= 2;
166+
mp_seq_clear(self->items, self->len + 1, self->alloc, sizeof(*self->items));
166167
}
167168
self->items[self->len++] = arg;
168169
return mp_const_none; // return None, as per CPython
@@ -178,6 +179,7 @@ STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) {
178179
// TODO: use alloc policy for "4"
179180
self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4);
180181
self->alloc = self->len + arg->len + 4;
182+
mp_seq_clear(self->items, self->len + arg->len, self->alloc, sizeof(*self->items));
181183
}
182184

183185
memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len);
@@ -199,6 +201,8 @@ STATIC mp_obj_t list_pop(uint n_args, const mp_obj_t *args) {
199201
mp_obj_t ret = self->items[index];
200202
self->len -= 1;
201203
memcpy(self->items + index, self->items + index + 1, (self->len - index) * sizeof(mp_obj_t));
204+
// Clear stale pointer from slot which just got freed to prevent GC issues
205+
self->items[self->len] = MP_OBJ_NULL;
202206
if (self->alloc > LIST_MIN_ALLOC && self->alloc > 2 * self->len) {
203207
self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc/2);
204208
self->alloc /= 2;
@@ -253,6 +257,7 @@ STATIC mp_obj_t list_clear(mp_obj_t self_in) {
253257
self->len = 0;
254258
self->items = m_renew(mp_obj_t, self->items, self->alloc, LIST_MIN_ALLOC);
255259
self->alloc = LIST_MIN_ALLOC;
260+
mp_seq_clear(self->items, 0, self->alloc, sizeof(*self->items));
256261
return mp_const_none;
257262
}
258263

@@ -368,6 +373,7 @@ void mp_obj_list_init(mp_obj_list_t *o, uint n) {
368373
o->alloc = n < LIST_MIN_ALLOC ? LIST_MIN_ALLOC : n;
369374
o->len = n;
370375
o->items = m_new(mp_obj_t, o->alloc);
376+
mp_seq_clear(o->items, n, o->alloc, sizeof(*o->items));
371377
}
372378

373379
STATIC mp_obj_list_t *list_new(uint n) {

0 commit comments

Comments
 (0)
0