@@ -91,6 +91,8 @@ static inline int
9191_md_check_consistency (MultiDictObject * md , bool update );
9292static inline int
9393_md_dump (MultiDictObject * md );
94+ static inline int
95+ _md_refdump (MultiDictObject * md );
9496
9597#define ASSERT_CONSISTENT (md , update ) assert(_md_check_consistency(md, update))
9698#else
@@ -102,12 +104,12 @@ _str_cmp(PyObject *s1, PyObject *s2)
102104{
103105 PyObject * ret = PyUnicode_RichCompare (s1 , s2 , Py_EQ );
104106 if (Py_IsTrue (ret )) {
105- Py_DECREF (ret );
107+ Py_XDECREF (ret );
106108 return 1 ;
107109 } else if (ret == NULL ) {
108110 return -1 ;
109111 } else {
110- Py_DECREF (ret );
112+ Py_XDECREF (ret );
111113 return 0 ;
112114 }
113115}
@@ -481,7 +483,7 @@ static inline int
481483_md_add_for_upd (MultiDictObject * md , Py_hash_t hash , PyObject * identity ,
482484 PyObject * key , PyObject * value )
483485{
484- Py_INCREF (identity );
486+ // Py_INCREF(identity);
485487 Py_INCREF (key );
486488 Py_INCREF (value );
487489 return _md_add_for_upd_steal_refs (md , hash , identity , key , value );
@@ -500,6 +502,7 @@ md_add(MultiDictObject *md, PyObject *key, PyObject *value)
500502 }
501503 int ret = _md_add_with_hash (md , hash , identity , key , value );
502504 ASSERT_CONSISTENT (md , false);
505+ Py_DECREF (key );
503506 Py_DECREF (identity );
504507 return ret ;
505508fail :
@@ -1010,16 +1013,15 @@ md_pop_one(MultiDictObject *md, PyObject *key, PyObject **ret)
10101013 if (_md_del_at (md , iter .slot , entry ) < 0 ) {
10111014 goto fail ;
10121015 }
1013- Py_DECREF (identity );
10141016 * ret = value ;
10151017 md -> version = NEXT_VERSION (md -> state );
1016- ASSERT_CONSISTENT ( md , false );
1018+ Py_DECREF ( identity );
10171019 return 1 ;
10181020 } else if (tmp < 0 ) {
10191021 goto fail ;
10201022 }
10211023 }
1022-
1024+ Py_DECREF ( identity );
10231025 ASSERT_CONSISTENT (md , false);
10241026 return 0 ;
10251027fail :
@@ -1084,7 +1086,7 @@ md_pop_all(MultiDictObject *md, PyObject *key, PyObject **ret)
10841086 }
10851087
10861088 * ret = lst ;
1087- Py_DECREF (identity );
1089+ Py_XDECREF (identity );
10881090 ASSERT_CONSISTENT (md , false);
10891091 return lst != NULL ;
10901092fail :
@@ -1877,19 +1879,19 @@ md_traverse(MultiDictObject *md, visitproc visit, void *arg)
18771879static inline int
18781880md_clear (MultiDictObject * md )
18791881{
1880- if (md -> used == 0 ) {
1881- return 0 ;
1882- }
1882+ // Remove This because sometimes tweaked multidicts or memory leaks speap
1883+ // through the cracks. if (md->used == 0) {
1884+ // return 0;
1885+ // }
18831886 md -> version = NEXT_VERSION (md -> state );
18841887
18851888 entry_t * entries = htkeys_entries (md -> keys );
18861889 for (Py_ssize_t pos = 0 ; pos < md -> keys -> nentries ; pos ++ ) {
18871890 entry_t * entry = entries + pos ;
1888- if (entry -> identity != NULL ) {
1889- Py_CLEAR (entry -> identity );
1890- Py_CLEAR (entry -> key );
1891- Py_CLEAR (entry -> value );
1892- }
1891+ // Py_CLEAR has null checks of it's own making it easier to free.
1892+ Py_CLEAR (entry -> identity );
1893+ Py_CLEAR (entry -> key );
1894+ Py_CLEAR (entry -> value );
18931895 }
18941896
18951897 md -> used = 0 ;
@@ -1995,6 +1997,44 @@ _md_dump(MultiDictObject *md)
19951997 printf ("\n" );
19961998 return 1 ;
19971999}
2000+
2001+ static inline int
2002+ _md_refdump (MultiDictObject * md )
2003+ {
2004+ htkeys_t * keys = md -> keys ;
2005+ printf ("Refcounts Dump %p [%zd from %zd usable %zd nentries %zd]\n" ,
2006+ (void * )md ,
2007+ md -> used ,
2008+ htkeys_nslots (keys ),
2009+ keys -> usable ,
2010+ keys -> nentries );
2011+ for (Py_ssize_t i = 0 ; i < htkeys_nslots (keys ); i ++ ) {
2012+ Py_ssize_t ix = htkeys_get_index (keys , i );
2013+ printf (" %zd -> %zd\n" , i , ix );
2014+ }
2015+ printf (" --------\n" );
2016+ entry_t * entries = htkeys_entries (keys );
2017+ for (Py_ssize_t i = 0 ; i < keys -> nentries ; i ++ ) {
2018+ entry_t * entry = & entries [i ];
2019+ PyObject * identity = entry -> identity ;
2020+ PyObject * key = entry -> key ;
2021+ PyObject * value = entry -> value ;
2022+ if (identity == NULL ) {
2023+ printf (" %zd [should be deleted]" , i );
2024+ } else {
2025+ printf (" %zd h=%20zd" , i , entry -> hash );
2026+ }
2027+ if (key != NULL ) {
2028+ printf (", k=%zd" , key -> ob_refcnt );
2029+ }
2030+ if (value != NULL ) {
2031+ printf (", v=%zd" , value -> ob_refcnt );
2032+ }
2033+ }
2034+ printf ("\n" );
2035+ return 1 ;
2036+ }
2037+
19982038#endif // NDEBUG
19992039
20002040#ifdef __cplusplus
0 commit comments