当前位置: 首页 > article >正文

python内存处理和常见的内存泄漏场景

python内存处理和常见的内存泄漏场景

一 python内存处理机制
手动垃圾回收:采用gc.collect()进行手动强制执行垃圾回收,采用变量赋值为空,等待下一轮python自动回收,采用del变量,直接删除
**引用计数(reference count):**垃圾回收机制会记录每个对象被其他对象所引用的次数。
**循环引用检测:**若对象之间存在相互引用,则对象间将形成一个环状结构,使得引用计数不会降为零,因此内存无法被自动回收,导致内存泄漏。
二常见的内存泄漏常见
1.循环引用:当两个或多个对象互相引用彼此时,它们之间就会形成一个循环。这样会导致 Python 的垃圾回收机制无法释放这些对象所占用的内存空间;

class LeakClass:
    def __init__(self):
        self.other_object = None

instance_a = LeakClass()
instance_b = LeakClass()

# 循环引用,导致内存泄露
instance_a.other_object = instance_b
instance_b.other_object = instance_a

2.全局变量和缓存:如果程序中有大量的全局变量和缓存,那么这些对象可能不会被垃圾回收器正确地释放。

cache = {}
def add_to_cache(key, value):
    global cache
    cache[key] = value

# 不断添加元素到缓存,导致内存泄露
for i in range(100000):
    add_to_cache(i, "value")

3.未关闭文件句柄:如果程序中打开了文件但没有及时关闭,那么这些文件句柄会一直占用内存直到程序退出。

# 打开文件,但未关闭文件句柄,导致内存泄露
file_handle = open("myfile.txt", "w")

4.计数器引用: 当一个对象的引用计数不正确时,会导致垃圾回收器无法正确地释放该对象的内存空间。这种情况通常会发生在使用 ctypes 库时。

import ctypes
def leaking_func(self):
    self.buffer = (ctypes.c_char * 1024)()

# 计数器引用,导致内存泄露
while True:
    leaking_func()

5.长期运行的循环:

def long_running_loop():
    while True:
        pass

# 长期运行的循环,会一直占用内存
long_running_loop()

6.大型数据结构的未释放:

def load_data():
    data = [i for i in range(1000000)]
    return data

# 调用函数获取大型数据结构,但不及时释放,导致内存泄露
big_data = load_data()

7.信号处理:

import signal

def handle_signal(signum, frame):
    pass

# 注册信号处理函数,但不移除导致内存泄露
signal.signal(signal.SIGUSR1, handle_signal)

8.外部资源的未释放:

import sqlite3

# 打开数据库连接,但不关闭连接,导致内存泄露
conn = sqlite3.connect('mydatabase.db')

9.循环中的生成器:

def generator():
    # 生成器函数
    for i in range(1000000):
        yield i

# 循环遍历生成器,但不释放引用,导致内存泄露
for item in generator():
    pass

10.不正确使用多进程和多线程:

import multiprocessing
import threading

def target_thread():
    while True:
        pass

# 创建多个进程或线程,但不关闭或结束,导致内存泄露
for i in range(2):
    multiprocessing.Process(target=target_thread).start()

for i in range(2):
    threading.Thread(target=target_thread).start()

11.滥用缓存:

cache = {}

def heavy_data_processing(input_data):
    # 需要费时地处理的数据
    output_data = input_data * 2
    return output_data

# 存储完整数据,而非必须的中间输出,导致内存泄露
while True:
    data = load_data()
    if data in cache:
        output = cache[data]
    else:
        output = heavy_data_processing(data)
        cache[data] = output

12.滥用全局变量:

def global_state_changing():
    global global_data
    global_data += 1

# 不断更改全局状态,导致内存泄露
while True:
    global_state_changing()

13.大量异常创建:

def exception_raising():
    raise Exception("Errors")

# 大量的异常创建,但并不处理异常,导致内存泄露
while True:
    try:
        exception_raising()
    except:
        pass

http://www.kler.cn/news/159668.html

相关文章:

  • 【从删库到跑路 | MySQL数据库总结篇】JDBC编程
  • 【论文】F1的单位是%还是1,mAP的单位是%还是1?答:F1的单位是1,mAP的单位是%
  • flutter的CircularProgressIndicator基本使用
  • 【UGUI】实现背包的常用操作
  • USTC Fall2023 高级人工智能期末考试回忆版
  • 力扣:196. 删除重复的电子邮箱(Python3)
  • go第三方包发布(短精细)
  • InnoDB存储引擎体系结构中的各个组件是如何协同工作的?
  • WVP-RPO开源项目搭建实践
  • 苹果TF签名全称TestFlight签名,需要怎么做才可以上架呢?
  • C++笔试题之回文数的判断
  • 【Redis6快速深入学习04】Redis字符串(String)的使用和原理
  • 【分布式微服务专题】从单体到分布式(一、SpringCloud项目初步升级)
  • FAQ:Reference篇
  • Android各版本引入的重要安全机制介绍
  • nodeJS爬虫-爬取虎嗅新闻
  • vos3000怎样设置落地的优先级
  • HXDSP2441-I2C(Inter-Integrated Circuit)
  • 麒麟系统图形化应用自启
  • 【微信小程序开发】学习小程序的模块化开发(自定义组件和分包加载)
  • MinIo 的操作与使用和避坑
  • Mysql行格式(记录格式)详解
  • Leetcode—2477.到达首都的最少油耗【中等】
  • 《PFL》论文阅读笔记
  • Docker 的基本概念和优势,以及在应用程序开发中的实际应用。
  • 基本数据类型与引用数据类型的区别(java基础)
  • 【软件测试】技术精选:Jmeter常见的几种报错
  • 云HIS:新一代云架构医院信息管理系统源码(java语言)
  • Flink流批一体计算(24):Flink SQL之mysql维表实时关联
  • 2、RocketMQ源码分析(二)