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应用场景可能不会出现这种问题。我只是有针对性做了一段编码。



posted @ 2012-02-10 17:54  Mimaoku  阅读(816)  评论(0)    收藏  举报