[Python-Dev] test_builtin failing on Windows

Tim Peters tim.one@home.com
Fri, 23 Feb 2001 15:25:25 -0500


> But only if run under a debug build *and* passing -O to Python:
>
> *And* only if the .pyc/.pyo files reachable from Lib/ are deleted
> before running it.

The explosion is here:

static int
com_make_closure(struct compiling *c, PyCodeObject *co)
{
	int i, free = PyTuple_GET_SIZE(co->co_freevars);

co-> is almost entirely filled with 0xdddddddd at this point (and in
particular, that's the value of co->co_freevars, which is why it blows up).
That bit pattern is the MS "dead landfill" value:  when the MS debug
libraries free() an object, they overwrite the space with 0xdd bytes.

Here's the call stack:

com_make_closure(compiling * 0x0063f5c4, PyCodeObject * 0x00a1b5b0)
    line 2108 + 6 bytes
com_test(compiling * 0x0063f5c4, _node * 0x008470d0)
    line 2164 + 13 bytes
com_node(compiling * 0x0063f5c4, _node * 0x008470d0
    line 3452 + 13 bytes
com_argument(compiling * 0x0063f5c4, _node * 0x0084a900,
    _object * * 0x0063f3b8)
    line 1516 + 16 bytes
com_call_function(compiling * 0x0063f5c4, _node * 0x00847124)
    line 1581 + 17 bytes
com_apply_trailer(compiling * 0x0063f5c4, _node * 0x008471d4)
    line 1764 + 19 bytes
com_power(compiling * 0x0063f5c4, _node * 0x008472b0)
    line 1792 + 24 bytes
com_factor(compiling * 0x0063f5c4, _node * 0x008472f0)
    line 1813 + 16 bytes
com_term(compiling * 0x0063f5c4, _node * 0x00847330)
    line 1823 + 16 bytes
com_arith_expr(compiling * 0x0063f5c4, _node * 0x00847370)
    line 1852 + 16 bytes
com_shift_expr(compiling * 0x0063f5c4, _node * 0x008473b0)
    line 1878 + 16 bytes
com_and_expr(compiling * 0x0063f5c4, _node * 0x008473f0)
    line 1904 + 16 bytes
com_xor_expr(compiling * 0x0063f5c4, _node * 0x00847430)
    line 1926 + 16 bytes
com_expr(compiling * 0x0063f5c4, _node * 0x0084a480)
    line 1948 + 16 bytes
com_comparison(compiling * 0x0063f5c4, _node * 0x008474b0)
    line 2002 + 16 bytes
com_not_test(compiling * 0x0063f5c4, _node * 0x008474f0)
    line 2077 + 16 bytes
com_and_test(compiling * 0x0063f5c4, _node * 0x008475e0)
    line 2094 + 24 bytes
com_test(compiling * 0x0063f5c4, _node * 0x0084b124)
    line 2178 + 24 bytes
com_node(compiling * 0x0063f5c4, _node * 0x0084b124)
    line 3452 + 13 bytes
com_if_stmt(compiling * 0x0063f5c4, _node * 0x00847620)
    line 2817 + 13 bytes
com_node(compiling * 0x0063f5c4, _node * 0x00847620)
    line 3431 + 13 bytes
com_file_input(compiling * 0x0063f5c4, _node * 0x007d4cc0)
    line 3660 + 13 bytes
compile_node(compiling * 0x0063f5c4, _node * 0x007d4cc0)
    line 3762 + 13 bytes
jcompile(_node * 0x007d4cc0, char * 0x0063f84c, compiling * 0x00000000)
    line 3870 + 16 bytes
PyNode_Compile(_node * 0x007d4cc0, char * 0x0063f84c)
    line 3813 + 15 bytes
parse_source_module(char * 0x0063f84c, _iobuf * 0x10261888)
    line 611 + 13 bytes
load_source_module(char * 0x0063f9a8, char * 0x0063f84c,
    _iobuf * 0x10261888)
    line 731 + 13 bytes
load_module(char * 0x0063f9a8, _iobuf * 0x10261888, char * 0x0063f84c,
    int 0x00000001)
    line 1259 + 17 bytes
import_submodule(_object * 0x1e1f6ca0 __Py_NoneStruct,
    char * 0x0063f9a8, char * 0x0063f9a8)
    line 1787 + 33 bytes
load_next(_object * 0x1e1f6ca0 __Py_NoneStruct,
    _object * 0x1e1f6ca0 __Py_NoneStruct, char * * 0x0063fabc,
    char * 0x0063f9a8, int * 0x0063f9a4)
    line 1643 + 17 bytes
import_module_ex(char * 0x00000000, _object * 0x00770d6c,
    _object * 0x00770d6c, _object * 0x1e1f6ca0 __Py_NoneStruct)
    line 1494 + 35 bytes
PyImport_ImportModuleEx(char * 0x007ae58c, _object * 0x00770d6c,
    _object * 0x00770d6c, _object * 0x1e1f6ca0 __Py_NoneStruct)
    line 1535 + 21 bytes
builtin___import__(_object * 0x00000000, _object * 0x007716ac)
    line 31 + 21 bytes
call_cfunction(_object * 0x00760080, _object * 0x007716ac,
    _object * 0x00000000)
    line 2740 + 11 bytes
call_object(_object * 0x00760080, _object * 0x007716ac,
    _object * 0x00000000)
    line 2703 + 17 bytes
PyEval_CallObjectWithKeywords(_object * 0x00760080,
    _object * 0x007716ac, _object * 0x00000000)
    line 2673 + 17 bytes
eval_code2(PyCodeObject * 0x007afe10, _object * 0x00770d6c,
    _object * 0x00770d6c, _object * * 0x00000000, int 0x00000000,
    _object * * 0x00000000, int 0x00000000, _object * * 0x00000000,
    int 0x00000000, _object * 0x00000000)
    line 1767 + 15 bytes
PyEval_EvalCode(PyCodeObject * 0x007afe10, _object * 0x00770d6c,
    _object * 0x00770d6c)
    line 341 + 31 bytes
run_node(_node * 0x007a8760, char * 0x00760dd0,
    _object * 0x00770d6c, _object * 0x00770d6c)
    line 935 + 17 bytes
run_err_node(_node * 0x007a8760, char * 0x00760dd0,
    _object * 0x00770d6c, _object * 0x00770d6c)
    line 923 + 21 bytes
PyRun_FileEx(_iobuf * 0x10261888, char * 0x00760dd0, int 0x00000101,
    _object * 0x00770d6c, _object * 0x00770d6c, int 0x00000001)
    line 915 + 21 bytes
PyRun_SimpleFileEx(_iobuf * 0x10261888, char * 0x00760dd0,
    int 0x00000001) line 628 + 30 bytes
PyRun_AnyFileEx(_iobuf * 0x10261888, char * 0x00760dd0,
    int 0x00000001)
    line 467 + 17 bytes
Py_Main(int 0x00000003, char * * 0x00760d90) line 296 + 44 bytes
main(int 0x00000003, char * * 0x00760d90) line 10 + 13 bytes
mainCRTStartup() line 338 + 17 bytes

Unsurprisingly, it's importing test_b2.py at this point.  So this is enough
to reproduce the problem:

First, make sure test_b2.pyo doesn't exist.  Then

> python_d -O
Adding parser accelerators ...
Done.
Python 2.1a2 (#10, Feb 23 2001, 14:19:33) [MSC 32 bit (Intel)] on win32
Type "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path.insert(0, "../lib/test")
[5223 refs]
>>> import test_b2

Boom.

Best guess is that I need a debug build to fail, because in the normal build
it's still referencing free()d memory anyway, but the normal MS malloc/free
don't overwrite free()d memory with trash (so the problem isn't noticed).
No guess as to why -O is needed.