検索
ホームページバックエンド開発Python チュートリアルPython のメモリ リークの分析と gc モジュールの使用法

一般的に、 Python では、メモリ リークの問題を解決するために、オブジェクトの参照カウントが使用され、参照カウントに基づいて自動ガベージ コレクションが実装されます。
Python には自動ガベージ コレクションがあるため、多くの初心者は、それ以来良い生活を送っており、メモリ リークに悩まされる必要がなくなったと誤解しています。しかし、Python ドキュメントの __del__() 関数の説明を注意深く見ると、このような好景気にも雲があることがわかります。以下はドキュメントからの抜粋です:

オブジェクトの参照カウントがゼロになるのを妨げる一般的な状況としては、次のようなものがあります。オブジェクト間の循環参照 (例: オブジェクトへの参照が二重にリンクされたリストや、親ポインターと子ポインターを持つツリー データ構造)。例外をキャッチした関数のスタック フレーム上 (sys.exc_traceback に保存されたトレースバックにより、スタック フレームが維持されます)、または対話モードで未処理の例外を発生させたスタック フレーム上のオブジェクトへの参照 (sys.exc_traceback に保存されたトレースバック)。 .last_traceback はスタック フレームを維持します)。

__del__() 関数によるオブジェクト間の循環参照がメモリ リークの主な原因であることがわかります
さらに、__del__() 関数を使用しない Python オブジェクト間の循環参照は、自動的にガベージ コレクションされる可能性があります

オブジェクトにメモリ リークがあるかどうかを確認するにはどうすればよいですか?

方法 1. オブジェクトを破棄する必要があると思われる場合 (つまり、参照カウントが 0 である場合)、sys.getrefcount(obj) を通じてオブジェクトの参照カウントを取得し、メモリ リークがあるかどうかを判断できます。戻り値が 0 かどうかに基づきます。返された参照カウントが 0 でない場合は、現時点ではオブジェクト obj をガベージ コレクターでリサイクルできないことを意味します。

方法 2: Python 拡張モジュール gc を使用して、リサイクルできないオブジェクトの詳細情報を表示することもできます。


まず、通常のテストコードを見てみましょう:

#--------------- code begin --------------
# -*- coding: utf-8 -*-
import gc
import sys

class CGcLeak(object):
  def __init__(self):
    self._text = '#'*10

  def __del__(self):
    pass

def make_circle_ref():
  _gcleak = CGcLeak()
#  _gcleak._self = _gcleak # test_code_1
  print '_gcleak ref count0:%d' % sys.getrefcount(_gcleak)
  del _gcleak
  try:
    print '_gcleak ref count1:%d' % sys.getrefcount(_gcleak)
  except UnboundLocalError:
    print '_gcleak is invalid!'

def test_gcleak():
  # Enable automatic garbage collection.
  gc.enable()
  # Set the garbage collection debugging flags.
  gc.set_debug(gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE | /
    gc.DEBUG_INSTANCES | gc.DEBUG_OBJECTS)

  print 'begin leak test...'
  make_circle_ref()

  print 'begin collect...'
  _unreachable = gc.collect()
  print 'unreachable object num:%d' % _unreachable
  print 'garbage object num:%d' % len(gc.garbage)

if __name__ == '__main__':
  test_gcleak()

test_gcleak() では、ガベージ コレクターのデバッグ フラグを設定した後、collect() を使用してガベージ コレクションを実行し、最後に、このガベージ コレクションで見つかった到達不能なガベージ オブジェクトの数とインタープリター全体のガベージ オブジェクトの数を出力します。 。

gc.garbage はリスト オブジェクトです。リスト項目は、ガベージ コレクターによって到達不能であることが検出されたものの、解放できない (つまり、リサイクルできない) オブジェクトです。ドキュメントの説明は次のとおりです: コレクターが到達不能であることが判明したが解放できなかったオブジェクト (収集不可能なオブジェクト) のリスト。
通常、gc.garbage 内のオブジェクトは参照リング内のオブジェクトです。 Python は、リング内のオブジェクトの __del__() 関数をどのような安全な順序で呼び出すことができるかわからないため、オブジェクトは常に gc.garbage 内に存在し、メモリ リークが発生します。安全な順序がわかっている場合は、参照サイクルを中断し、del gc.garbage[:] を実行してガベージ オブジェクト リストをクリアします。

上記のコードの出力は次のとおりです (# の後の文字列は作成者が追加したコメントです):

#-----------------------------------------
begin leak test...
# 变量 _gcleak 的引用计数为 2.
_gcleak ref count0:2
# _gcleak 变为不可达(unreachable)的非法变量.
_gcleak is invalid!
# 开始垃圾回收
begin collect...
# 本次垃圾回收发现的不可达的垃圾对象数为 0.
unreachable object num:0
# 整个解释器中的垃圾对象数为 0.
garbage object num:0
#-----------------------------------------

_gcleak オブジェクトの参照カウントが正しく、どのオブジェクトでもメモリ リークが発生していないことがわかります。

make_circle_ref() の test_code_1 ステートメントをコメントアウトしない場合:

_gcleak._self = _gcleak

つまり、_gcleak がそれ自体への循環参照を形成するようにします。上記のコードを再度実行すると、出力は次のようになります:

#-----------------------------------------
begin leak test...
_gcleak ref count0:3
_gcleak is invalid!
begin collect...
# 发现可以回收的垃圾对象: 地址为 012AA090,类型为 CGcLeak.
gc: uncollectable <CGcLeak 012AA090>
gc: uncollectable <dict 012AC1E0>
unreachable object num:2
#!! 不能回收的垃圾对象数为 1,导致内存泄漏!
garbage object num:1
#-----------------------------------------

Visible オブジェクトにメモリ リークがあります。 !余分な dict ガベージは、リークされた _gcleak オブジェクトの辞書です。出力される辞書情報は次のとおりです。

{'_self': <__main__.CGcLeak object at 0x012AA090>, '_text': '##########'}

それ自体への循環参照に加えて、複数のオブジェクト間の循環参照もメモリ リークを引き起こす可能性があります。簡単な例は次のとおりです:

#--------------- code begin --------------

class CGcLeakA(object):
  def __init__(self):
    self._text = '#'*10

  def __del__(self):
    pass

class CGcLeakB(object):
  def __init__(self):
    self._text = '*'*10

  def __del__(self):
    pass

def make_circle_ref():
  _a = CGcLeakA()
  _b = CGcLeakB()
  _a._b = _b # test_code_2
  _b._a = _a # test_code_3
  print 'ref count0:a=%d b=%d' % /
    (sys.getrefcount(_a), sys.getrefcount(_b))
#  _b._a = None  # test_code_4
  del _a
  del _b
  try:
    print 'ref count1:a=%d' % sys.getrefcount(_a)
  except UnboundLocalError:
    print '_a is invalid!'
  try:
    print 'ref count2:b=%d' % sys.getrefcount(_b)
  except UnboundLocalError:
    print '_b is invalid!'

#--------------- code end ----------------

このテスト後の出力結果は次のとおりです:


#-----------------------------------------
begin leak test...
ref count0:a=3 b=3
_a is invalid!
_b is invalid!
begin collect...
gc: uncollectable <CGcLeakA 012AA110>
gc: uncollectable <CGcLeakB 012AA0B0>
gc: uncollectable <dict 012AC1E0>
gc: uncollectable <dict 012AC0C0>
unreachable object num:4
garbage object num:2
#-----------------------------------------
_a オブジェクトと _b オブジェクトの両方でメモリ リークが発生していることがわかります。この 2 つは循環参照であるため、ガベージ コレクターはそれらをリサイクルする方法がわかりません。つまり、どのオブジェクトの __del__() 関数を最初に呼び出すべきかがわかりません。

メモリ リークを避けるために、次のいずれかの方法を使用して循環参照を解除します。



1. make_circle_ref() の test_code_2 ステートメントをコメント化します。 2. make_circle_ref() の test_code_3 ステートメントをコメント化します。 3. make_circle_ref() 内の test_code_4 ステートメントのコメントを解除します。

対応する出力結果は次のようになります:

#-----------------------------------------
begin leak test...
ref count0:a=2 b=3 # 注:此处输出结果视情况变化.
_a is invalid!
_b is invalid!
begin collect...
unreachable object num:0
garbage object num:0
#-----------------------------------------

結論: Python の gc には比較的強力な機能があり、たとえば gc.set_debug(gc.DEBUG_LEAK) を設定すると、循環参照によるメモリ リークをチェックできます。開発中にメモリ リーク チェックを実行し、公開時にメモリ リークがないことを確認すると、Python のガベージ コレクション間隔を延長したり、ガベージ コレクション メカニズムを積極的にオフにしたりすることができるため、操作効率が向上します。
声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
Python vs. C:比較されたアプリケーションとユースケースPython vs. C:比較されたアプリケーションとユースケースApr 12, 2025 am 12:01 AM

Pythonは、データサイエンス、Web開発、自動化タスクに適していますが、Cはシステムプログラミング、ゲーム開発、組み込みシステムに適しています。 Pythonは、そのシンプルさと強力なエコシステムで知られていますが、Cは高性能および基礎となる制御機能で知られています。

2時間のPython計画:現実的なアプローチ2時間のPython計画:現実的なアプローチApr 11, 2025 am 12:04 AM

2時間以内にPythonの基本的なプログラミングの概念とスキルを学ぶことができます。 1.変数とデータ型、2。マスターコントロールフロー(条件付きステートメントとループ)、3。機能の定義と使用を理解する4。

Python:主要なアプリケーションの調査Python:主要なアプリケーションの調査Apr 10, 2025 am 09:41 AM

Pythonは、Web開発、データサイエンス、機械学習、自動化、スクリプトの分野で広く使用されています。 1)Web開発では、DjangoおよびFlask Frameworksが開発プロセスを簡素化します。 2)データサイエンスと機械学習の分野では、Numpy、Pandas、Scikit-Learn、Tensorflowライブラリが強力なサポートを提供します。 3)自動化とスクリプトの観点から、Pythonは自動テストやシステム管理などのタスクに適しています。

2時間でどのくらいのPythonを学ぶことができますか?2時間でどのくらいのPythonを学ぶことができますか?Apr 09, 2025 pm 04:33 PM

2時間以内にPythonの基本を学ぶことができます。 1。変数とデータ型を学習します。2。ステートメントやループの場合などのマスター制御構造、3。関数の定義と使用を理解します。これらは、簡単なPythonプログラムの作成を開始するのに役立ちます。

プロジェクトの基本と問題駆動型の方法で10時間以内にコンピューター初心者プログラミングの基本を教える方法は?プロジェクトの基本と問題駆動型の方法で10時間以内にコンピューター初心者プログラミングの基本を教える方法は?Apr 02, 2025 am 07:18 AM

10時間以内にコンピューター初心者プログラミングの基本を教える方法は?コンピューター初心者にプログラミングの知識を教えるのに10時間しかない場合、何を教えることを選びますか...

中間の読書にどこでもfiddlerを使用するときにブラウザによって検出されないようにするにはどうすればよいですか?中間の読書にどこでもfiddlerを使用するときにブラウザによって検出されないようにするにはどうすればよいですか?Apr 02, 2025 am 07:15 AM

fiddlereveryversings for the-middleの測定値を使用するときに検出されないようにする方法

Python 3.6にピクルスファイルをロードするときに「__Builtin__」モジュールが見つからない場合はどうすればよいですか?Python 3.6にピクルスファイルをロードするときに「__Builtin__」モジュールが見つからない場合はどうすればよいですか?Apr 02, 2025 am 07:12 AM

Python 3.6のピクルスファイルのロードレポートエラー:modulenotFounderror:nomodulenamed ...

風光明媚なスポットコメント分析におけるJieba Wordセグメンテーションの精度を改善する方法は?風光明媚なスポットコメント分析におけるJieba Wordセグメンテーションの精度を改善する方法は?Apr 02, 2025 am 07:09 AM

風光明媚なスポットコメント分析におけるJieba Wordセグメンテーションの問題を解決する方法は?風光明媚なスポットコメントと分析を行っているとき、私たちはしばしばJieba Wordセグメンテーションツールを使用してテキストを処理します...

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

MantisBT

MantisBT

Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。