質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

1057閲覧

bytearray のメモリが開放されているのか不安なのですが

100H

総合スコア5

メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/02/27 14:56

前提・実現したいこと

昔C、C++を使用していて、最近 Python を始めた者です。
環境は Python2.7 です

該当のソースコード

self.data = bytearray(['A','B','C'])
newdata = bytearray(['V','W','X','Y','Z'])
self.data = newdata

試したこと

上記のようなコードを書くと、self.data は VWXYZ の5バイトのデータになるのですが、最初に確保した ABC の3バイトのデータを格納したメモリ領域は開放されるのでしょうか?
開放が必要な場合、明示的な開放方法はあるのでしょうか?ご教示願います。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Pythonではガベージコレクタという仕組みが背後で自動的に作動しており、不要になったメモリ領域は自動で解放されます。

Pythonでガベージコレクタとして動いている仕組みは現時点では二種類存在しています。

参考カウンタ

すべてのオブジェクトは内部的に参照カウントの値を持ちます。単純化した例を以下に示します。

python

1# 「10」というオブジェクト(厳密にはリテラル10を評価して得られるオブジェクト)をaというグローバル変数に束縛 2# これによって「10」の参照カウントの値は1になる 3a = 10 4 5# リストを作ってaをappendすることで、「10」の参照カウントの値は2になる 6lst = [] 7lst.append(a) 8

参照カウントの値が0になったとき、そのオブジェクトはメモリ上から「解放」されます。

たとえばdel adel lstを実行してそれぞれの名前の束縛を解除すれば、「10」のオブジェクトはメモリ上から消えます。
lstを消した結果「10」も解放されるのが不思議に感じるかもしれませんが、これはlstのオブジェクトを消すときにこちらで引き取って参照カウントの値をデクリメントしているからです。通常Pythonを書いているときはこれを意識する必要はありませんが、C拡張を書くときは気にする必要があります)。

gcモジュールで使えるGC

参照カウンタはエレガントな仕組みですが、循環参照として知られる問題があります。

python

1a = [] 2b = [] 3a.append(b) 4b.append(a) 5del a 6del b

ablistが互いに参照を持ち合っているので、それぞれの参照カウントの値が0にならず、これらは参照カウンタでは解放されません。

これを補うために、世代別ガベージコレクションが参照カウンタとは別に走っており、参照カウンタでは解放できなかったオブジェクトを解放します。

これも自動で行われるので、通常意識する必要はありません。

質問文のコードの場合

基本的には解放されると見て問題ありません。

python

1self.data = bytearray(['A','B','C']) 2newdata = bytearray(['V','W','X','Y','Z']) 3self.data = newdata # ここでbytearray(['A','B','C'])の参照カウントが0になり、解放される

もちろん、self.dataが実はプロパティで代入されたものをどこか他のところの記録しているとか、bytearrayが凶暴な代物で生成したオブジェクトを記録しているとか、マルチスレッドで処理が走っていてこの二行の間に運悪くself.dataを拾って他のところに参照を作ってしまうとか、色んな可能性は考えられますが、そういうことがない素直なプログラムであれば問題なく参照カウントで解放されるでしょう。

参考

はじめに — Python 3.8.2 ドキュメント
gc --- ガベージコレクタインターフェース — Python 3.8.2 ドキュメント

投稿2020/02/27 16:09

hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

100H

2020/02/27 16:52

ありがとうございました。C等ではメモリリークは頻発する問題で、 Python のような扱いに不安を覚えていました。アドバイスを頂きました通り、あまり煩雑な持たれあいをしないように取り扱うように注意します。
guest

0

ベストアンサー

最初に確保した ABC の3バイトのデータを格納したメモリ領域は開放されるのでしょうか?

開放が必要な場合、明示的な開放方法はあるのでしょうか?ご教示願います。

変数のスコープを抜ける等で参照されなくなった場合は、適当なタイミングでガレージコレクション (GC) で開放されます。
以下のようにして明示的に GC を走らせることもできます。

python

1import gc 2gc.collect()

また、del で明示的に変数を削除できますが、削除した瞬間にメモリから開放されることは保証されません。

開放が必要な場合、明示的な開放方法はあるのでしょうか?

Python を使用する場合、参照されなくなった変数は適当なタイミングで開放されるので、C/C++ のようにメモリから明示的に開放することは基本しなくてよいです。

環境は Python2.7 です

今年の4月で Python 2 のサポートは終了するので、なにか特殊な事情がなければ、Python 3 で勉強したほうがよいと思います。
2系と3系は互換性がないので、コードを移植するとなると面倒です。

投稿2020/02/27 15:11

tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

100H

2020/02/27 16:58

ありがとうございました。C等の性分で開放しないと不安になる所があって質問させて頂きました。Python 2系は 2.7 で頭打ちというのは存じているのですが、現在使用している linux Mint が標準が2系で3系を追加させて混在という面倒な状況になっていまして2系を使っています。今年のアップデートで本来昨年予定されていた3系への一本化が完了次第以降する予定です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問