Quantcast
Channel: CodeSection,代码区,Python开发技术文章_教程 - CodeSec
Viewing all articles
Browse latest Browse all 9596

CPython实现 - 整型对象 - 编译验证

$
0
0

修改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 未本地化版本许可协议 进行许可


Viewing all articles
Browse latest Browse all 9596

Trending Articles