python源代码的一个问题
今天读了《Python源码剖析》这本书。书中讲到了PyIntObject,挺有意思。Python将整数区分为常用的小整数(small int)和大整数。其中小整数在python初始化时直接做了缓存。
通常通过PyInt_FromLong来创建一个PyIntObject对象,所以PyInt_FromLong判断数值是属于小整数时直接从缓存中获取,大整数时从free list中得到(无论小整数或大整数都存在于block_list)。
于是我下载了Python-2.7.2的源代码。阅读代码我发现了PyIntObject的一个问题。
下面这个测试函数就能说明。
void TestInt(void)
{
PyIntObject * want1 = (PyIntObject*)PyInt_FromLong(1);
PyIntObject * want10000 = (PyIntObject*)PyInt_FromLong(10000);
TraceInt("want1", want1);
TraceInt("want10000", want10000);
want1->ob_type->tp_dealloc((PyObject*)want1);
TraceInt("want1", want1);
want10000 = (PyIntObject*)PyInt_FromLong(10000);
TraceInt("want1", want1);
TraceInt("want10000", want10000);
want1 = (PyIntObject*)PyInt_FromLong(1);
TraceInt("want1", want1);
}
void TraceInt(char * name, PyIntObject *val)
{
printf("%s value is %d\n", name , val->ob_ival);
}
输出结果:
want1 value is 1
want10000 value is 10000
want1 value is 1
want1 value is 10000
want10000 value is 10000
want1 value is 10000
看看int_dealloc:
static void int_dealloc(PyIntObject *v)
{
if (PyInt_CheckExact(v)) {
Py_TYPE(v) = (struct _typeobject *)free_list;
free_list = v;
}
else
Py_TYPE(v)->tp_free((PyObject *)v);
}
对象释放时,回到freelist中,并置于列表头。
如果先释放一个小整数,下次再请求一个大整数。之前的小整数对象将作为返回对象,并且值修改成了大整数。
当然实际Python应用场景可能不会出现这种问题。我只是有针对性做了一段编码。

浙公网安备 33010602011771号