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

你可能感兴趣的:(python,python,jvm,开发语言)