diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 5ba99514d29691..a5b6a3d873ba1d 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -15657,52 +15657,46 @@ PyUnicode_InternFromString(const char *cp) } -#if defined(WITH_VALGRIND) || defined(__INSURE__) static void unicode_release_interned(void) { + Py_ssize_t pos = 0; + PyObject *s, *ignored_value; + if (interned == NULL || !PyDict_Check(interned)) { return; } - PyObject *keys = PyDict_Keys(interned); - if (keys == NULL || !PyList_Check(keys)) { - PyErr_Clear(); - return; - } /* Since unicode_release_interned() is intended to help a leak detector, interned unicode strings are not forcibly deallocated; rather, we give them their stolen references back, and then clear and DECREF the interned dict. */ - - Py_ssize_t n = PyList_GET_SIZE(keys); #ifdef INTERNED_STATS - fprintf(stderr, "releasing %zd interned strings\n", n); + fprintf(stderr, "releasing %zd interned strings\n", PyDict_Size(interned)); Py_ssize_t immortal_size = 0, mortal_size = 0; #endif - for (Py_ssize_t i = 0; i < n; i++) { - PyObject *s = PyList_GET_ITEM(keys, i); + while (PyDict_Next(interned, &pos, &s, &ignored_value)) { if (PyUnicode_READY(s) == -1) { Py_UNREACHABLE(); } switch (PyUnicode_CHECK_INTERNED(s)) { - case SSTATE_INTERNED_IMMORTAL: - Py_SET_REFCNT(s, Py_REFCNT(s) + 1); + case SSTATE_INTERNED_IMMORTAL: + Py_SET_REFCNT(s, Py_REFCNT(s) + 1); #ifdef INTERNED_STATS - immortal_size += PyUnicode_GET_LENGTH(s); + immortal_size += PyUnicode_GET_LENGTH(s); #endif - break; - case SSTATE_INTERNED_MORTAL: - Py_SET_REFCNT(s, Py_REFCNT(s) + 2); + break; + case SSTATE_INTERNED_MORTAL: + Py_SET_REFCNT(s, Py_REFCNT(s) + 2); #ifdef INTERNED_STATS - mortal_size += PyUnicode_GET_LENGTH(s); + mortal_size += PyUnicode_GET_LENGTH(s); #endif - break; - case SSTATE_NOT_INTERNED: - /* fall through */ - default: - Py_UNREACHABLE(); + break; + case SSTATE_NOT_INTERNED: + /* fall through */ + default: + Py_UNREACHABLE(); } _PyUnicode_STATE(s).interned = SSTATE_NOT_INTERNED; } @@ -15711,11 +15705,9 @@ unicode_release_interned(void) "total size of all interned strings: %zd/%zd mortal/immortal\n", mortal_size, immortal_size); #endif - Py_DECREF(keys); PyDict_Clear(interned); Py_CLEAR(interned); } -#endif /********************* Unicode Iterator **************************/ @@ -16209,18 +16201,7 @@ _PyUnicode_Fini(PyThreadState *tstate) int is_main_interp = _Py_IsMainInterpreter(tstate); if (is_main_interp) { -#if defined(WITH_VALGRIND) || defined(__INSURE__) - /* Insure++ is a memory analysis tool that aids in discovering - * memory leaks and other memory problems. On Python exit, the - * interned string dictionaries are flagged as being in use at exit - * (which it is). Under normal circumstances, this is fine because - * the memory will be automatically reclaimed by the system. Under - * memory debugging, it's a huge source of useless noise, so we - * trade off slower shutdown for less distraction in the memory - * reports. -baw - */ unicode_release_interned(); -#endif /* __INSURE__ */ } Py_CLEAR(state->empty); diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 4b658f847bc12b..b0e6005cce2254 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1259,14 +1259,14 @@ finalize_interp_types(PyThreadState *tstate, int is_main_interp) _PyAsyncGen_Fini(tstate); _PyContext_Fini(tstate); - _PyDict_Fini(tstate); _PyList_Fini(tstate); + _PyUnicode_Fini(tstate); + _PyDict_Fini(tstate); _PyTuple_Fini(tstate); _PySlice_Fini(tstate); _PyBytes_Fini(tstate); - _PyUnicode_Fini(tstate); _PyFloat_Fini(tstate); _PyLong_Fini(tstate); }