Skip to content

Commit e19cadb

Browse files
committed
Correct one of the "MemoryError oddities":
the traceback would grow each time a MemoryError is raised.
1 parent a986dfa commit e19cadb

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

Lib/test/test_exceptions.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,24 @@ class MyException(Exception, metaclass=Meta):
596596
"Exception ValueError: ValueError() "
597597
"in <class 'KeyError'> ignored\n")
598598

599+
600+
def test_MemoryError(self):
601+
# PyErr_NoMemory always raises the same exception instance.
602+
# Check that the traceback is not doubled.
603+
import traceback
604+
def raiseMemError():
605+
try:
606+
"a" * (sys.maxsize // 2)
607+
except MemoryError as e:
608+
tb = e.__traceback__
609+
else:
610+
self.fail("Should have raises a MemoryError")
611+
return traceback.format_tb(tb)
612+
613+
tb1 = raiseMemError()
614+
tb2 = raiseMemError()
615+
self.assertEqual(tb1, tb2)
616+
599617
def test_main():
600618
run_unittest(ExceptionTests)
601619

Python/errors.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,17 @@ PyErr_NoMemory(void)
321321

322322
/* raise the pre-allocated instance if it still exists */
323323
if (PyExc_MemoryErrorInst)
324+
{
325+
/* Clear the previous traceback, otherwise it will be appended
326+
* to the current one.
327+
*
328+
* The following statement is not likely to raise any error;
329+
* if it does, we simply discard it.
330+
*/
331+
PyException_SetTraceback(PyExc_MemoryErrorInst, Py_None);
332+
324333
PyErr_SetObject(PyExc_MemoryError, PyExc_MemoryErrorInst);
334+
}
325335
else
326336
/* this will probably fail since there's no memory and hee,
327337
hee, we have to instantiate this class

0 commit comments

Comments
 (0)