メモリリークに悩まされる

アバター
いわん
記事: 32
登録日時: 9年前

メモリリークに悩まされる

投稿記事 by いわん » 2年前

スクリプト解析プログラムをデバッグモードで試験中にメモリリークを検出。
式アイテムのオブジェクトリスト解放時に delete してないのが原因でした。

割とよくあるバグ。
でも問題はそこではなくて、解析にまるまる一日かかってしまったこと(;^_^A
集中力が無くなってしまいました。途中睡魔に負けて昼寝してしまう始末(笑)
若いころはもっと集中力あったんですけどね、今は経験値でなんとかごまかしている感じです(´-ω-`)

メモリリーク.PNG
メモリリーク発生
メモリリーク.PNG (30.68 KiB) 閲覧数: 538 回

アバター
usao
記事: 1889
登録日時: 12年前

Re: メモリリークに悩まされる

投稿記事 by usao » 2年前

pExp なるポインタ型変数を使い回しているように見えるけど,特段使い回す理由が無いならば
スコープを各 new ~ delete の範囲に制限しても問題なさそうに見える.
で,そしたらスマートポインタがどうのでその辺の面倒なところを自動化できる可能性もありそうな?

アバター
いわん
記事: 32
登録日時: 9年前

Re: メモリリークに悩まされる

投稿記事 by いわん » 2年前

usao さんが書きました:
2年前
スマートポインタがどうのでその辺の面倒なところを自動化できる可能性もありそうな?
スマートポインタのことをよく知らないので、
ポインタをコピーしたり上書きしてもほっとけば最後には自動的に実体を削除してくれるんですか。
だとしたら有効そうですね。
ポインタはクラスのメンバに保持していてデストラクタで削除するようにしてたんですが、
スクリプトにエラーがあって中断した場合、ワークのポインタをメンバにコピーせずに終了していた
にメモリリークが発生していました。

アバター
usao
記事: 1889
登録日時: 12年前

Re: メモリリークに悩まされる

投稿記事 by usao » 2年前

ものすごくざっくりと言うと

newとdeleteを自前で書いてるとわりとミスる(deleteしないパスができるとか,逆に多重にdeleteするパスができる)ので,
「俺はある条件が満たされたらdeleteするぜ!」っていう仕組みを実装したもの(スマートポインタ)にその辺の管理は任せれば楽

…っていう話ですね.

まぁ,スマートポインタさえ使えばそれで何もかもが魔法のようにうまいこと解決してもらえるわけではなくて,例によって「こういう書き方をしてしまうと… → こうなってしまうぞ!(やめろ!)」っていうような注意事項は相応にあるのですが,

そういう「やめろ!」な事柄をしないように気を付けること VS 自前でミスらないコードを書くこと

で天秤にかけると,(そもそもこういうことを考えている場面というのは,後者側の難易度が問題となっている場面であるから)前者がいいかな,っていう感じ.

アバター
usao
記事: 1889
登録日時: 12年前

Re: メモリリークに悩まされる

投稿記事 by usao » 2年前

まともな情報源を見て,こういう実験をしてみて(なんなら「やめろ!」の実験とかもしてみて)雰囲気を掴んでみると良いかと.

CODE:

class X  //テスト用.deleteされた(→デストラクタが呼ばれた)を見る用
{
    int m_v;
    X( int v ) : m_v(v) {}
    ~X(){   std::cout<< "dtor " << m_v << std::endl;    }
};

int main()
{
    std::cout << "BeginTest(1)" << std::endl;
    {//(1) shared_ptr のデストラクタが X を始末することを見るテスト
        std::shared_ptr<X> sp1 = std::make_shared<X>( 1 );
    }
    std::cout << "EndTest(1)" << std::endl;

    std::cout << "BeginTest(2)" << std::endl;
    {//(2)途中で別のを管理することにされたら直前まで管理してた X の始末はどうなるのか?を見るテスト
        auto sp10 = std::make_shared<X>( 10 );
        auto sp20 = std::make_shared<X>( 20 );

        std::cout << "Before sp10=sp20" << std::endl;
        sp10 = sp20;
        std::cout << "after sp10=sp20" << std::endl;

        std::cout << "Before sp10.reset( new X(7) )" << std::endl;
        sp10.reset( new X(7) );
        std::cout << "After sp10.reset( new X(7) )" << std::endl;
        std::cout << "Before sp20.reset( new X(90) )" << std::endl;
        sp20.reset( new X(90) );
        std::cout << "After sp20.reset( new X(90) )" << std::endl;
    }
    std::cout << "EndTest(2)" << std::endl;

    return 0;
}

アバター
いわん
記事: 32
登録日時: 9年前

Re: メモリリークに悩まされる

投稿記事 by いわん » 2年前

>usaoさん
サンプルソースありがとうござます。
ポインタを値型の変数のように扱えるようになるんですね。これは使えますね。
vectorに入れたポインタも後始末を考えなくてもいいですし。
でも新しい技術を取り入れようとすると全体に対応したくなるし、
また新しいライブラリの地層が積み上がるなぁ・・・( 一一)