修改python整数对象的 int_print 方法
static int values[10]; static int refcounts[10]; /* ARGSUSED */ static int int_print(PyIntObject *v, FILE *fp, int flags) /* flags -- not used but required by interface */ { PyIntObject* intObjectPtr; PyIntBlock *p = block_list; PyIntBlock *last = NULL; int count = 0; int i; while(p != NULL) { ++count; last = p; p = p->next; } intObjectPtr = last->objects; intObjectPtr += N_INTOBJECTS - 1; printf("%ld pointer address @%p\n", v->ob_ival, v); for(i=0; i<10; ++i, --intObjectPtr) { values[i] = intObjectPtr -> ob_ival; refcounts[i] = intObjectPtr -> ob_refcnt; } printf("value: "); for(i=0; i<8; ++i) { printf("%d\t", values[i]); } printf("\n"); printf("refcnt :"); for(i=0; i<8; ++i) { printf("%d\t", refcounts[i]); } printf("\n"); printf("block_list count: %d\n", count); printf("free_list address: %p\n", free_list); fprintf(fp, "%ld", v->ob_ival); return 0; } 一些解释intObjectPtr 是一个 PyIntObject 指针
p 是指向 block_list 的 PyIntBlock 指针
last 是 PyIntBlock 指针,最终指向了 block_list 的最后一个 PyIntBlock 元素
count 用来统计 block_list 的长度
intObjectPtr = last->objects; intObjectPtr += N_INTOBJECTS - 1;根据上面这两行
intObjectPtr 最终指向了 block_list 的最后一个 PyIntBlock 元素的 objects 数组中的最后一个 PyIntObject 对象
printf("%ld pointer address @%p\n", v->ob_ival, v);这里打印了传入参数 v ( PyIntObject 指针)的值
接下来
for(i=0; i<10; ++i, --intObjectPtr) { values[i] = intObjectPtr -> ob_ival; refcounts[i] = intObjectPtr -> ob_refcnt; }values 和 refcount 存放了从 block_list 中倒数10个 PyIntObject 元素的值和引用数量
接下来就将这个10个中的前8个打印出来了
然后打印了一下 block_list 的长度(也就是链表中 PyIntBlock 的个数)
然后打印了 free_list 的起始地址
这段代码就是这样 主要是打印
改完代码接下来编译一下
./configure -prefix=/opt/apps/python make make install先看一下输入1会输出什么
>>> x = 1 >>> x 1 element address @0x35 1 pointer address @0x26a64a8 value: -5 -4 -3 -2 -1 0 1 2 refcnt: 1 1 2 1 32 112 53 30 block_list count: 8 free_list address: @0x26d63d8 1我们分析一下上面的输出
@0x36 是1这个 PyIntObject 的实际地址
@0x26a64a8 x 的指针的值
value: -5 -4 -3 -2 -1 0 1 2 refcnt: 1 1 2 1 32 112 53 30这两行说明了在初始化Python小整数对象的时候
-5是最先初始化的
也说明了在Python初始化的已经有很多指针指向了这些小整数对象, 特别是-1 0 1
当前有8个 block_list
free_list 链表的起始地址 @0x26d63d8
>>> a = 10086 >>> a 10086 element address @0x4 10086 pointer address @0x23913a8 value: -5 -4 -3 -2 -1 0 1 2 refcnt: 1 1 2 1 32 112 49 30 block_list count: 8 free_list address: @0x23913c0 10086 >>> b = 10086 >>> b 10086 element address @0x4 10086 pointer address @0x23913c0 value: -5 -4 -3 -2 -1 0 1 2 refcnt: 1 1 2 1 32 112 49 30 block_list count: 8 free_list address: @0x23913d8 10086上面这些输出
首先a,b 都是指向的同一个地址 @0x4
然后初始化a的时候的free_list地址为 @0x23913c0
而b指针的值为 @0x23913c0
从这里就可以看出指针分配都是从 free_list 中获取的
接下来我们删除b
>>> del b >>> a 10086 element address @0x4 10086 pointer address @0x23913a8 value: -5 -4 -3 -2 -1 0 1 2 refcnt: 1 1 2 1 32 112 49 30 block_list count: 8 free_list address: @0x23913c0 10086可以看到b的指针地址已经被重新放到了 free_list 中
>>> c = -5 >>> c -5 element address @0x5 -5 pointer address @0x2361538 value: -5 -4 -3 -2 -1 0 1 2 refcnt: 5 1 2 1 32 112 49 30 block_list count: 8 free_list address: @0x23913c0 -5 >>> d = -5 >>> d -5 element address @0x6 -5 pointer address @0x2361538 value: -5 -4 -3 -2 -1 0 1 2 refcnt: 6 1 2 1 32 112 49 30 block_list count: 8 free_list address: @0x23913c0 -5注意这里-5是小整数
我们可以看到 refcnt 的增加
同时 free_list 是没有发生变化的
EOF
本作品采用 知识共享署名-相同方式共享 3.0 未本地化版本许可协议 进行许可