👻
security
  • 计算机技术
  • OWASP TOP 10
  • 名词解释
  • 1
    • 常见端口利用
    • F5 big-ip从环境搭建到漏洞复现
    • 红队资源
  • About
    • APT
      • 海莲花(APT-C-00)
        • 样本分析
      • 毒云藤(APT-C-01)
        • 大规模钓鱼攻击活动披露
        • 2020上半年针对我重要机构定向攻击活动揭秘
      • 响尾蛇(T-APT-04)
        • 利用WebSocket隧道的新型攻击活动披露
      • 蔓灵花(APT-C-08)
        • 移动平台攻击活动揭露
      • 蓝宝菇(APT-C-12)
        • 组织使用云存储技术发起的最新攻击活动披露
      • 双尾蝎组织(APT-C-23)
        • 针对中东地区的最新攻击活动
      • Lazarus(APT-C-26)
        • 暴风行动 -利用MATA框架针对数字货币行业的攻击活动揭秘
      • Fancy Bear(APT-C-28)
        • 携小众压缩包诱饵对北约、中亚目标的定向攻击分析
      • 肚脑虫组织(APT-C-35)
        • 使用升级版数字武器针对周边地区的攻击活动
        • 针对巴基斯坦的攻击活动
      • 拍拍熊(APT-C-37)
      • 军刀狮(APT-C-38)
      • 蓝色魔眼(APT-C-41)
        • 组织首次针对我国重要机构定向攻击活动披露
      • 美人鱼(Infy)
        • 使用最新的Foudre后门进行攻击活动的分析
    • 各类靶场讲解
      • sqli-labs
      • upload-labs
      • xss-labs
    • CISP题库
    • Docker
      • Docker基线
        • docker基线-概述
        • 推荐一
        • 推荐二
        • 推荐三
        • 推荐四
        • 推荐五
        • 推荐六
      • 命令与选项
      • 基于Docker的固件模拟
      • 固件相关
      • Docker 私有仓库搭建
      • 基础命令的背后
      • 渗透思路调研
      • Docker容器环境检测方法【代码】
    • 浏览器
    • markdown
    • 密码学
    • 内网渗透TIPS
    • 网络扫描
    • 正则表达式
  • 操作系统
    • Android
      • APK终端安全分析法
      • 应用审计指南
        • 通用审计方法
    • IOS
      • 应用审计指南
    • Linux
      • 反弹shell
      • 基线检查
      • SHELL编程
      • 实战技能
    • windows
      • BACKDOOR with 权限维持
      • 磁盘取证实验
      • 基线检查
      • 免杀抓取明文
      • payload下载方式
      • powershell
      • 日志分析
        • 分析工具
      • Untitled
  • 数据库
    • db2
    • mysql
      • webshell写入
      • 基础知识
      • 核心技术
      • 高级应用
    • oracle
      • webshell写入
    • SQLserver
      • webshell写入
  • 中间件
    • apache
      • 基线检查
      • 日志审计
    • iis
      • 基线检查
      • 7.5解析绕过漏洞
    • nginx
      • 基线检查
    • tomcat
      • 基线检查
  • 编程语言
    • C
    • Java
      • webshell
        • 查杀Java web filter型内存马
        • Filter/Servlet型内存马的扫描抓捕与查杀
        • 基于内存 Webshell 的无文件攻击技术研究
        • 基于tomcat的内存 Webshell 无文件攻击技术
        • Tomcat 内存马检测
      • 代码审计
      • 代码审计指南
      • 浅析Java命令执行
      • 相关框架简介及漏洞
    • PHP
      • 代码审计
      • 破解DVWA-admin密码
      • webshell
        • 常见php一句话webshell解析
        • PHP Webshell Hidden Learning
        • Webshell免杀研究
        • Webshell那些事-攻击篇
        • 过D盾webshell分享
      • 相关框架简介及漏洞
    • python
      • 安全编码规范-代码审计
      • 编码规范
      • fishc
      • 某教程涉及脚本
      • POC编写相关
      • python秘籍
        • 上半部分
        • 下半部分
      • 安全方面的内容
        • Python Opcode逃逸笔记
        • 虚拟机逃逸
      • with-EXCEL
      • 相关框架简介及漏洞
      • 源码剖析
        • 多线程和GIL锁
        • Set容器
        • 统一内存管理
        • 信号处理机制
        • 循环垃圾回收器
        • 字符串对象PyStringObject
        • 整数对象PyIntObject
        • 字节码和虚拟机
    • 汇编
    • Javascript
      • Tampermonkey Script
  • AIGC
    • howtouse
  • 网络
    • CCNA
  • 漏洞类型及讲解
    • 综合
    • 技术分享
      • 暴力破解与信息泄露
      • 信息泄露漏洞_java
      • sqli-with-java
      • python远程命令执行与SSRF
    • SQL-Injectoin
    • Cross-Site Scripting
      • 跨站的艺术-XSS入门与介绍
      • 跨站的艺术-XSS Fuzzing 的技巧
      • 给开发者的终极XSS防护备忘录
      • AngularJS特性的 XSS
    • 文件操作
      • 文件包含
  • how-to-use
    • Acunetix(AWVS)
      • 安装到使用
      • 编写AWVS脚本探测web services
      • 简单分析-web方面
      • 流量分析特征
    • burpsuite
      • 导出报告方式
      • captcha-killer
      • FAKE-IP
      • JSFind
      • 编写插件绕过WAF
    • Cobalt Strike
      • Cobalt Strike Powershell过360+Defender上线
    • FOFA
    • GDB
    • PowerSh
      • 获得Powershell命令的历史记录
      • 深入分析PowerShell的两面性
      • 内网渗透利器之PowerSploit
      • PoC:滥用PowerShell Core
      • 如何绕过PowerShell访问限制并实现PowerShell代码执行
      • 工具包
      • 无powershell运行powershell方法总结
    • sheji
    • sqlmap
      • Atlas修改SQLMap tampers 绕过WAF/IDS/IPS
      • 内核分析
      • 检测剖析
      • tamper
      • UDF
      • --os-shell
      • sqlmapapi
      • with burp
      • 网络特征
    • Matlab
    • Metasploit
      • 与Powershell
    • NESSUS
      • 流量分析特征
      • Untitled
    • Network MapTools
      • 流量特征修改
      • 识别主机指纹
    • waf
      • ngx-lua-waf
      • modsecurity
由 GitBook 提供支持
在本页
  • 整数对象的结构
  • 整数对象的缓存
  • 整数对象的初始化
  • 整数对象的创建
  • 整数对象的回收
  • 整数对象的释放
  • 整数对象的操作符

这有帮助吗?

  1. 编程语言
  2. python
  3. 源码剖析

整数对象PyIntObject

整数对象的结构

整数对象是固定大小的Python对象,内部只有一个ob_ival保存实际的整数值。

typedef struct {
    PyObject_HEAD
    long ob_ival;
} PyIntObject;

整数对象的缓存

为了最大限度的减少内存分配和垃圾回收,Python对整数对象设计了缓存。整数对象的缓存由两种类别构成:

  1. 小整数对象: 在Python启动时创建,永远不会回收

  2. 其他整数对象:创建时分配,回收时先缓存;在最高代的垃圾回收中整体回收

在Python启动时会创建一批默认值为[5, 257)的小整数对象,存储在small_ints中。这些整数对象的生命周期为Python的生命周期,不会被回收。Python只所以这样处理是因此解释器内部会频繁用到这些小整数,如果每次都分配-回收-再分配显然效率不高,不如创建后一直保留用空间换时间。

#ifndef NSMALLPOSINTS
#define NSMALLPOSINTS           257
#endif
#ifndef NSMALLNEGINTS
#define NSMALLNEGINTS           5
#endif
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
/* References to small integers are saved in this array so that they
   can be shared.
   The integers that are saved are those in the range
   -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

可以通过id命令查看小整数对象的特性。

id(246)
id(256)
Out[55]: 31363504L
id(256)
Out[56]: 31363504L  # id不会改变
id(257)
Out[53]: 60259096L
id(257)
Out[54]: 60259024L # id会改变

通过上面的例子我们可以知道,其他整数对象使用的内存是不固定的,申请时分配释放时回收。当然,这个回收并不一定是返还给系统内存,整数对象系统本身会缓存一部分整数对象。下面通过整数对象系统的初始化揭露整数的缓存方案。

整数对象的初始化

当Python初始化时会调用_PyInt_Init函数进行整数的初始化。

int
_PyInt_Init(void)
{
    PyIntObject *v;
    int ival;
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
    for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++) {
          if (!free_list && (free_list = fill_free_list()) == NULL)
                    return 0;
        /* PyObject_New is inlined */
        v = free_list;
        free_list = (PyIntObject *)Py_TYPE(v);
        PyObject_INIT(v, &PyInt_Type);
        v->ob_ival = ival;
        small_ints[ival + NSMALLNEGINTS] = v;
    }
#endif
    return 1;
}

缓存会用到数据结构PyIntBlock以及block_list和free_list链表。PyInBlock用来一次申请多个整数对象的内存,然后再一个个用作PyIntObject,并且通过域next链接到block_list链表上。free_list中是空闲的PyIntObject的链表。fill_free_list初始化后的内存结构如下。

然后通过_PyInt_init初始化为小整数,并将其指针存储到samll_ints数组中加快查找。_PyInt_init初始化后的内存结构如下。

我们可以看到整数对象通过PyIntBlock和free_list进行内存申请和缓存的。

整数对象的创建

当新创建一个整数对象时,先从free_list中查找空闲的整数对象,如果有则直接使用;否则会重新分配PyIntBlock结构并进行初始化。

PyObject *
PyInt_FromLong(long ival)
{
    register PyIntObject *v;
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
    if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {       # 是小整数则直接使用
        v = small_ints[ival + NSMALLNEGINTS];
        Py_INCREF(v);
#ifdef COUNT_ALLOCS
        if (ival >= 0)
            quick_int_allocs++;
        else
            quick_neg_int_allocs++;
#endif
        return (PyObject *) v;
    }
#endif
    if (free_list == NULL) {
        if ((free_list = fill_free_list()) == NULL)             # 没有空闲的整数对象则分配
            return NULL;
    }
    /* Inline PyObject_New */
    v = free_list;
    free_list = (PyIntObject *)Py_TYPE(v);
    PyObject_INIT(v, &PyInt_Type);
    v->ob_ival = ival;
    return (PyObject *) v;
}

创建一个新的整数257之后的数据结构:

整数对象的回收

当整数对象的引用计数归零时则对其进行回收,由函数int_free操作

static void
int_free(PyIntObject *v)
{
    Py_TYPE(v) = (struct _typeobject *)free_list;
    free_list = v;
}

可以看到被回收的整数对象被连接到free_list链表中。这里有个问题,整数对象的内存什么时候才真正释放呢?

整数对象的释放

原来整数对象的真正释放是在最高代的GC中进行,当GC运行时会调用PyInt_ClearFreeList进行整数对象内存的释放PyInt_ClearFreeList对整个block_list进行遍历,如果其中所有的整数对象的引用计数都为零,则释放整个block。可见整数对象的内存是以PyIntBlock为单位申请和释放的。

int
PyInt_ClearFreeList(void)
{
    PyIntObject *p;
    PyIntBlock *list, *next;
    int i;
    int u;                      /* remaining unfreed ints per block */
    int freelist_size = 0;
    list = block_list;
    block_list = NULL;
    free_list = NULL;
    while (list != NULL) {
        u = 0;
        for (i = 0, p = &list->objects[0];
             i < N_INTOBJECTS;
             i++, p++) {
            if (PyInt_CheckExact(p) && p->ob_refcnt != 0)
                u++;
        }
        next = list->next;
        if (u) {                        # 遍历block发现其有引用计数部位零的对象
            list->next = block_list;
            block_list = list;
            # 将PyIntBlock中引用计数为零的整数对象重新挂到free_list链表中
            for (i = 0, p = &list->objects[0];
                 i < N_INTOBJECTS;
                 i++, p++) {
                if (!PyInt_CheckExact(p) ||
                    p->ob_refcnt == 0) {
                    Py_TYPE(p) = (struct _typeobject *)
                        free_list;
                    free_list = p;
                }
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
               /* 这段代码没有作用。小整数对象都在small_ints中?
                */
                else if (-NSMALLNEGINTS <= p->ob_ival &&
                         p->ob_ival < NSMALLPOSINTS &&
                         small_ints[p->ob_ival +
                                    NSMALLNEGINTS] == NULL) {
                    Py_INCREF(p);
                    small_ints[p->ob_ival +
                               NSMALLNEGINTS] = p;
                }
#endif
            }
        }
        else {              # 整个block的整数对象引用计数均为零,释放整个block
            PyMem_FREE(list);
        }
        freelist_size += u;
        list = next;
    }
    return freelist_size;
}

整数对象的操作符

整数对象定义了许多操作符,可以通过以下代码自行查看。

static PyNumberMethods int_as_number = {
    (binaryfunc)int_add,        /*nb_add*/
    (binaryfunc)int_sub,        /*nb_subtract*/
    (binaryfunc)int_mul,        /*nb_multiply*/
    (binaryfunc)int_classic_div, /*nb_divide*/
    (binaryfunc)int_mod,        /*nb_remainder*/
    (binaryfunc)int_divmod,     /*nb_divmod*/
    (ternaryfunc)int_pow,       /*nb_power*/
    (unaryfunc)int_neg,         /*nb_negative*/
    (unaryfunc)int_int,         /*nb_positive*/
    (unaryfunc)int_abs,         /*nb_absolute*/
    (inquiry)int_nonzero,       /*nb_nonzero*/
    (unaryfunc)int_invert,      /*nb_invert*/
    (binaryfunc)int_lshift,     /*nb_lshift*/
    (binaryfunc)int_rshift,     /*nb_rshift*/
    (binaryfunc)int_and,        /*nb_and*/
    (binaryfunc)int_xor,        /*nb_xor*/
    (binaryfunc)int_or,         /*nb_or*/
    int_coerce,                 /*nb_coerce*/
    (unaryfunc)int_int,         /*nb_int*/
    (unaryfunc)int_long,        /*nb_long*/
    (unaryfunc)int_float,       /*nb_float*/
    (unaryfunc)int_oct,         /*nb_oct*/
    (unaryfunc)int_hex,         /*nb_hex*/
    0,                          /*nb_inplace_add*/
    0,                          /*nb_inplace_subtract*/
    0,                          /*nb_inplace_multiply*/
    0,                          /*nb_inplace_divide*/
    0,                          /*nb_inplace_remainder*/
    0,                          /*nb_inplace_power*/
    0,                          /*nb_inplace_lshift*/
    0,                          /*nb_inplace_rshift*/
    0,                          /*nb_inplace_and*/
    0,                          /*nb_inplace_xor*/
    0,                          /*nb_inplace_or*/
    (binaryfunc)int_div,        /* nb_floor_divide */
    (binaryfunc)int_true_divide, /* nb_true_divide */
    0,                          /* nb_inplace_floor_divide */
    0,                          /* nb_inplace_true_divide */
    (unaryfunc)int_int,         /* nb_index */
};
PyTypeObject PyInt_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "int",
    sizeof(PyIntObject),
    0,
    (destructor)int_dealloc,                    /* tp_dealloc */
    (printfunc)int_print,                       /* tp_print */
    0,                                          /* tp_getattr */
    0,                                          /* tp_setattr */
    (cmpfunc)int_compare,                       /* tp_compare */
    (reprfunc)int_to_decimal_string,            /* tp_repr */
    &int_as_number,                             /* tp_as_number */
    0,                                          /* tp_as_sequence */
    0,                                          /* tp_as_mapping */
    (hashfunc)int_hash,                         /* tp_hash */
    0,                                          /* tp_call */
    (reprfunc)int_to_decimal_string,            /* tp_str */
    PyObject_GenericGetAttr,                    /* tp_getattro */
    0,                                          /* tp_setattro */
    0,                                          /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
        Py_TPFLAGS_BASETYPE | Py_TPFLAGS_INT_SUBCLASS,          /* tp_flags */
    int_doc,                                    /* tp_doc */
    0,                                          /* tp_traverse */
    0,                                          /* tp_clear */
    0,                                          /* tp_richcompare */
    0,                                          /* tp_weaklistoffset */
    0,                                          /* tp_iter */
    0,                                          /* tp_iternext */
    int_methods,                                /* tp_methods */
    0,                                          /* tp_members */
    int_getset,                                 /* tp_getset */
    0,                                          /* tp_base */
    0,                                          /* tp_dict */
    0,                                          /* tp_descr_get */
    0,                                          /* tp_descr_set */
    0,                                          /* tp_dictoffset */
    0,                                          /* tp_init */
    0,                                          /* tp_alloc */
    int_new,                                    /* tp_new */
    (freefunc)int_free,                         /* tp_free */
};

上一页字符串对象PyStringObject下一页字节码和虚拟机

最后更新于4年前

这有帮助吗?

image
image
image