メモリリーク

アバター
spaaaark・∀・
記事: 66
登録日時: 12年前
住所: 埼玉
連絡を取る:

メモリリーク

投稿記事 by spaaaark・∀・ » 12年前

僕はこの前、素数のプログラムについての質問に答えたが、その際に、

( ˘⊖˘) 。o(待てよ、もしかして自分のプログラムもメモリリークしてないか??)

と思い、今日実際に試してみた。すると

     _人人人人人人人人人人人人人人人人人人人人_
( ◠‿◠ )☛>出力ウィンドウを99%埋め尽くすメモリリーク通知<
      ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄

▂▅▇█▓▒░('ω')░▒▓█▇▅▂うわあああああああああああ

ってなった。で、その原因。

クラスのインスタンスをdeleteしてない

…orz
で、とりあえずインスタンスをちゃんと終了時にdeleteしようと思った。そして、

_人人人人人人_
>stack overflow<
 ̄Y^Y^Y^Y^Y^Y^ ̄


思わず目を疑った。そして気づいたこと。

なんでデストラクタでdelete thisしたの…呼び出されない…

ってことで、インスタンスをnewで統一して、終了処理にちゃんとdeleteを打ち込んだ。すると、

よかった…メモリリーク完全に消えた…(´・ω・`)
…以後クラスのインスタンスには気を付けようと思います(´;ω;`)
最後に編集したユーザー spaaaark・∀・ on 2013年8月01日(木) 17:41 [ 編集 1 回目 ]

ISLe
記事: 2650
登録日時: 14年前

Re: メモリリーク

投稿記事 by ISLe » 12年前

デストラクタはdeleteでインスタンスを解体する際に呼び出されるので、デストラクタでdeleteすると再帰的に呼び出されてたいへんなことになります。

実体宣言したときはdeleteしなくてもデストラクタが呼び出されます。
変数のライフサイクルに対して曖昧なままnew/deleteに統一して事なきを得るというのは問題を先送りにしているだけで良くないと思います。

アバター
spaaaark・∀・
記事: 66
登録日時: 12年前
住所: 埼玉
連絡を取る:

RE: メモリリーク

投稿記事 by spaaaark・∀・ » 12年前

そうですよね…。一応解決してはいましたが、疑問は残っています。
ただ、クラスの中身として別のクラスの実体宣言をしていた自分の操作に引っかかっています。
つまり、それでクラスを解体するタイミングを見失ってしまい、大量のメモリリークが発生したようにも思えるのですが、違うのでしょうか。

訂正後は、取り込みたいクラスのポインタ型を使いたいクラスのメンバ変数にしましたが、これでは実体宣言されておらず、ユーザーが実体宣言を
関数内(僕の場合はコンストラクタ)で行い、デストラクタでちゃんとそのクラスを解体するようにしました。
そこで…、実体を直接宣言するのと、new演算子経由でインスタンスを生成するのでは、これってどのような違いがあって、どう使い分ければいいんでしょうかね…(´・ω・`)?

(長くなりそうなら後々掲示板にスレッド立てます。とりあえず、様子見。)

ISLe
記事: 2650
登録日時: 14年前

Re: メモリリーク

投稿記事 by ISLe » 12年前

クラスを解体するタイミングを見失うというのがよく分かりませんが。
適切なコードでデストラクタが適切に呼び出されないのだとしたら処理系としてかなりの問題です。
コード側に問題がある可能性がはるかに高いと思いますが。

基本型の変数の初期化のようにコンストラクタが初期化のために呼ばれます。
基本型の変数は宣言されたブロックを抜けて使えなくなりますが、使えなくなる前にデストラクタが呼ばれます。

new演算子で確保されたメモリを初期化するためにコンストラクタは呼ばれます。
delete演算子でメモリを解放する前にデストラクタは呼ばれます。

適切に対応させて使っている限り問題になることはないはずですが。
最後に編集したユーザー ISLe on 2013年8月02日(金) 00:13 [ 編集 1 回目 ]

naohiro19
記事: 256
登録日時: 14年前

Re: メモリリーク

投稿記事 by naohiro19 » 12年前

std::auto_ptr/std::shared_prtを使うとメモリリークは起こりません。

アバター
spaaaark・∀・
記事: 66
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: メモリリーク

投稿記事 by spaaaark・∀・ » 12年前

ISLe さんが書きました:クラスを解体するタイミングを見失うというのがよく分かりませんが。
適切なコードでデストラクタが適切に呼び出されないのだとしたら処理系としてかなりの問題です。
コード側に問題がある可能性がはるかに高いと思いますが。

基本型の変数の初期化のようにコンストラクタが初期化のために呼ばれます。
基本型の変数は宣言されたブロックを抜けて使えなくなりますが、使えなくなる前にデストラクタが呼ばれます。

new演算子で確保されたメモリを初期化するためにコンストラクタは呼ばれます。
delete演算子でメモリを解放する前にデストラクタは呼ばれます。

適切に対応させて使っている限り問題になることはないはずですが。
ありがとうございます。一応、「実体宣言は関数の終わりで解体され、newで生成したものはdeleteによって好きなタイミングで解体できる。」
と自分なりに解釈してみましたが、こんな感じでよろしいでしょうか。もちろん、解体忘れは論外として、です。

アバター
spaaaark・∀・
記事: 66
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: メモリリーク

投稿記事 by spaaaark・∀・ » 12年前

naohiro19 さんが書きました:std::auto_ptr/std::shared_prtを使うとメモリリークは起こりません。
ありがとうございます。調べてみたところ、解体を忘れたインスタンス等をプログラム終了時に自動的に解体してくれるSTLのようですね。
解体忘れを自動的に修復してくれそうな機能です。気になる際に使用してみようと思います。
情報提供ありがとうございました><!

ISLe
記事: 2650
登録日時: 14年前

Re: メモリリーク

投稿記事 by ISLe » 12年前

spaaaark・∀・ さんが書きました:ありがとうございます。一応、「実体宣言は関数の終わりで解体され、newで生成したものはdeleteによって好きなタイミングで解体できる。」
と自分なりに解釈してみましたが、こんな感じでよろしいでしょうか。もちろん、解体忘れは論外として、です。
解釈は概ね合ってます。
正確には関数ではなく『ブロック』が実体宣言に影響するのですが。

基本中の基本なので、自分なりではなく、規格書などの資料を調べてきちんとしっかり押さえておくべきかと思います。

『生存範囲(ライフサイクル)』は『可視範囲(スコープ)』に比べて解説記事での扱いが少ない印象を受けますけどね。
もちろんそれぞれ別物なので気を付けてください。

ISLe
記事: 2650
登録日時: 14年前

Re: メモリリーク

投稿記事 by ISLe » 12年前

spaaaark・∀・ さんが書きました:ありがとうございます。調べてみたところ、解体を忘れたインスタンス等をプログラム終了時に自動的に解体してくれるSTLのようですね。
解体忘れを自動的に修復してくれそうな機能です。気になる際に使用してみようと思います。
情報提供ありがとうございました><!
ネイティブなポインタだとポインタが指すオブジェクトの面倒を見てくれませんが、スマートポインタは『スマートポインタ自身が解体されるとき』スマートポインタが指すオブジェクトを(必要ならば)解体します。

『スマートポインタ自身が解体されるとき』がキモです。
生存範囲(ライフサイクル)をきちんと理解せず誤った使い方をすると二重解体等の極めて発見しにくいバグを生むことになります。
最後に編集したユーザー ISLe on 2013年8月03日(土) 18:44 [ 編集 1 回目 ]

アバター
spaaaark・∀・
記事: 66
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: メモリリーク

投稿記事 by spaaaark・∀・ » 12年前

ISLe さんが書きました:
spaaaark・∀・ さんが書きました:ありがとうございます。一応、「実体宣言は関数の終わりで解体され、newで生成したものはdeleteによって好きなタイミングで解体できる。」
と自分なりに解釈してみましたが、こんな感じでよろしいでしょうか。もちろん、解体忘れは論外として、です。
解釈は概ね合ってます。
正確には関数ではなく『ブロック』が実体宣言に影響するのですが。

基本中の基本なので、自分なりではなく、規格書などの資料を調べてきちんとしっかり押さえておくべきかと思います。

『生存範囲(ライフサイクル)』は『可視範囲(スコープ)』に比べて解説記事での扱いが少ない印象を受けますけどね。
もちろんそれぞれ別物なので気を付けてください。
ありがとうございます。重要なことですので、自分で調べてみようと思います。

アバター
spaaaark・∀・
記事: 66
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: メモリリーク

投稿記事 by spaaaark・∀・ » 12年前

ISLe さんが書きました:
spaaaark・∀・ さんが書きました:ありがとうございます。調べてみたところ、解体を忘れたインスタンス等をプログラム終了時に自動的に解体してくれるSTLのようですね。
解体忘れを自動的に修復してくれそうな機能です。気になる際に使用してみようと思います。
情報提供ありがとうございました><!
ネイティブなポインタだとポインタが指すオブジェクトの面倒を見てくれませんが、スマートポインタは『スマートポインタ自身が解体されるとき』スマートポインタが指すオブジェクトを(必要ならば)解体します。

『スマートポインタ自身が解体されるとき』がキモです。
生存範囲(ライフサイクル)をきちんと理解せず誤った使い方をすると二重解体等の極めて発見しにくいバグを生むことになります。
ありがとうございます。先の記事の調査結果を参考にしながら、こちらも使ってみようと思います。