new unbounded memory leak in exception handling?

I've constructed an example program that does not leak memory in Python 2.x, but causes unbounded memory allocation in Python 3.1. Here is the code:
import gc import sys
class E(Exception): def __init__(self, fn): self.fn = fn def call(self): self.fn()
def f(): raise E(f)
a = E(f) while True: print(len(gc.get_objects())) try: a.call() except E: # get exception value in a python2/3 portable way a = sys.exc_info()[1]
Every time through the loop, the length of gc.get_objects() increases by 7 under Python 3.1. I believe this is a regression error, since Python 2.x does not exhibit the same behaviour.
Can anybody confirm this?
Greg Hewgill http://hewgill.com

On Tue, 17 Nov 2009 at 10:31, Greg Hewgill wrote:
I've constructed an example program that does not leak memory in Python 2.x, but causes unbounded memory allocation in Python 3.1. Here is the code:
import gc import sys
class E(Exception): def __init__(self, fn): self.fn = fn def call(self): self.fn()
def f(): raise E(f)
a = E(f) while True: print(len(gc.get_objects())) try: a.call() except E: # get exception value in a python2/3 portable way a = sys.exc_info()[1]
Every time through the loop, the length of gc.get_objects() increases by 7 under Python 3.1. I believe this is a regression error, since Python 2.x does not exhibit the same behaviour.
Can anybody confirm this?
I think you want to take a look at PEP 3134. And then please file a doc bug to have someone update the documentation of sys.exc_info, since the advice in the warning box is no longer valid in Python 3.
--David (RDM)

On Tue, Nov 17, 2009 at 08:40:37AM -0500, R. David Murray wrote:
I think you want to take a look at PEP 3134. And then please file a doc bug to have someone update the documentation of sys.exc_info, since the advice in the warning box is no longer valid in Python 3.
Thanks for the pointer, I understand the cause now. I had read the warning in the description of sys.exc_info, but I hadn't realised that Python was (now) implicitly saving the traceback for me. I was able to solve this memory leak by explicitly clearing __traceback__:
except E: # get exception value in a python2/3 portable way a = sys.exc_info()[1] a.__traceback__ = None
I have added a doc bug issue for this: http://bugs.python.org/issue7340
Greg Hewgill http://hewgill.com
participants (2)
-
Greg Hewgill
-
R. David Murray