目前学习到第三章PyStringObject的内容,在最后一小节Hack PyStringObject操作的时候,作者并没有给源代码,或者说没有直接说明如何修改源代码,这里是我的一些探索。
运行环境:
window10
vs2010
python2.7.13,编译的是PC目录里面的VS9.0的项目
这是原文中的描述:
作者说是通过在string_ength中添加代码,而这个函数实际上是这样的:
static Py_ssize_t
string_length(PyStringObject *a)
{
return Py_SIZE(a);
}
同时,我在stringobject.c文件中找不到ShowCharacter()函数,于是我打算自己写一个,然后加入string_length()函数,看看执行len()的结果,代码如下:
static Py_ssize_t
string_length(PyStringObject *a)
{
ShowCharacter();
return Py_SIZE(a);
}
其中ShowCharacter()代码和原文一致,但是这样编译出来的python,会在打开的时候卡死,然后退出,我猜是ShowCharacter()的问题,于是在前面输出一行文字:
static Py_ssize_t
string_length(PyStringObject *a)
{
printf("begin");
ShowCharacter();
return Py_SIZE(a);
}
果不其然,编译以后,打开python,命令行中会输出很多begin,然后直接退出,就是ShowCharacter()的问题了,目前还不太清楚问题具体出在哪,但是至少知道了一件事,当我们运行python时,它的内部会执行string_length()函数,我猜测在执行期间,运行到ShowCharacter()函数,这个函数内容会调用一些还未初始化的变量/类型,导致程序出错。
最后,为了实现这个功能,我先尝试了修改函数参数,加入一个flag参数,默认值为false,然后如果flag为true时,这个函数执行ShowCharacter(),但不幸的时,加入这个参数,系统会编译的时候报错,可能是其他用到这个string_length函数的地方不兼容,于是,我便尝试让ShowCharacter()在满足某些条件的情况下,才执行,最终,调整参数,实现了这个结果,代码如下:
static Py_ssize_t
string_length(PyStringObject *a)
{
// -----------------------
if (a->ob_size >= 500)
{
ShowCharacter();
}
// -----------------------
return Py_SIZE(a);
}
这样一来,我们可以设定一个长度大于500的字符串s,调用len(s)来间接查看字符缓冲区的引用变化。最终结果如下: