(Python)内存管理

前言

        内存泄漏在编程中是一个严重的问题,可能导致程序性能下降、系统不稳定甚至崩溃。

目录

危害

风险

动态内存分配

引用计数

内存池

垃圾回收

设计原则


危害

  1. 性能下降:可用内存减少,导致系统频繁进行内存交换,使程序运行速度变慢。
  2. 不稳定:内存耗尽可能导致程序出现异常、崩溃或产生不可预测的结果。
  3. 资源浪费:系统资源被无效占用,影响其他程序的正常运行。

风险

  1. 资源未释放:如果打开的文件、网络连接、数据库连接等资源在使用后没有正确关闭和释放,随着程序的运行,这些未释放的资源会不断累积,占用越来越多的内存。
  2. 无限增长的数据结构:例如,不断向一个列表或字典添加元素,而没有在适当的时候删除不再需要的部分,可能导致数据结构无限增长,消耗大量内存。
  3. 循环引用:对象之间的循环引用可能导致它们的引用计数永远不为零,即使它们不再被程序的其他部分直接使用,也无法被垃圾回收器回收。
  4. 缓存未清理:一些程序为了提高性能会使用缓存,但如果缓存中的数据不再被使用时没有及时清理,也会导致内存占用不断增加。

动态内存分配

        在 Python 中,动态内存分配是自动处理的。

        当您创建对象(例如列表、字典、类的实例等)时,Python 会自动为这些对象分配所需的内存并为该对象维护一个引用计数。当这些对象不再被引用时(引用计数变为 0 ),Python 的垃圾回收机制会自动回收它们所占用的内存。

 

引用计数

        这是 Python 内存管理的基础机制。每个对象都有一个引用计数,记录着有多少个地方正在引用它。当引用计数变为 0 时,该对象就会被立即释放。

测试范例

        引用数统计方法:采用sys模块的getrefcount函数去获取变量的引用数.

import sys
d = [1, 2, 3]
# 一开始引用次数为1
# 若调用getrefcount函数 引用次数+1 为2
# print(sys.getrefcount(d))
d_dict = {}
person_list = ["张三", "李四", '老王', "杜甫"]

for p in person_list:
    d_dict[p] = d
    print(sys.getrefcount(d))

# 删除变量d_dict后
del d_dict
# 手动触发垃圾回收
print(sys.getrefcount(d))

内存池

        这种存储方式通过复用已有的字符串对象,减少了内存分配和释放的操作,提高了性能和内存使用效率。

在 Python 中,以下类型的对象可能会进入内存池:

  1. 小整数对象(范围通常是 [-5, 256] 之间的整数)。
  2. 短字符串(长度较短且经常使用的字符串)。

验证方法

        两个字符串变量指向的都是同一个id

a = "hello"
b = "hello"
print(id(a) == id(b))  

垃圾回收

Python 中主要使用以下两种垃圾回收机制

  1. 引用计数:这是 Python 最基本的垃圾回收机制。每个对象都有一个引用计数,当引用计数变为 0 时,对象就会被立即回收。

  2. 循环引用垃圾回收器:用于处理循环引用导致的内存无法释放的情况。它使用了标记 - 清除算法或者分代回收算法来检测和回收不可达的对象。

         标记 - 清除

  1. 标记阶段:从根对象(例如正在运行的函数的局部变量和全局变量)开始,沿着对象之间的引用关系进行遍历,将所有可达的对象进行标记。

  2. 清除阶段:对未被标记的对象进行回收,释放它们所占用的内存空间。

        分代回收的策略 

        将对象分为不同的代(通常是 0 代、1 代、2 代),

       并根据不同代的特点和对象的生存时间来决定何时进行垃圾回收,以提高垃圾回收的效率。

 

设计原则

        熟悉 Python 中对象的引用计数机制,那我们的程序设计最好遵守下面的设计原则,以此避免内存泄露的事件.

 

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Marst·Writer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值