EN JP CN

CL.MLK.ASSIGN

CL.MLK.ASSIGN

代入演算子のメモリ リーク

これは演算子 = のメモリリークの可能性を通知するクラスレベル (CL) のチェッカーです。Klocwork は、コンストラクタで動的メモリ割り当てを行うクラスが演算子 = の対応するポインターを上書きし、前のメモリを解放せず、および/または適切なリファレンスカウンターを減分しない場合に、CL.MLK.ASSIGN をレポートします。これはメモリリークにつながる可能性があります。

脆弱性とリスク

メモリリークは、アプリケーションで余分なメモリを消費させます。これによって他のアプリケーションが使用できるメモリ量が減り、結果的に、オペレーティングシステムにページングを開始させ、システム速度を低下させます。重大な場合、アプリケーションがメモリ制限に達して、クラッシュする可能性があります。

脆弱コード例 1

1    class C {
2    public:
3        C() { ip = new int; }
4        ~C() { delete ip; }
5        C& operator=(const C& rhs) {
6            if (this == &rhs) return *this;
7            ip = new int;      // memory pointed by ip is leaked
8            *ip = *rhs.ip;
9            return *this;
10        }
11   private:
12       C(const C&);
13       int* ip;
14   };

この例では、ip がポイントするメモリは上書きされる前に解放されません。コンストラクタでこのポインターにメモリが割り当てられるため、この代入はメモリリークにつながる可能性があり、これは Klocwork によって CL.MLK.ASSIGN とレポートされます。

修正コード例 1

1    class C {
2    public:
3        C() { ip = new int; }
4        ~C() { delete ip; }
5        C& operator=(const C& rhs) {
6            if (this == &rhs) return *this;
7            delete ip;
8            ip = new int;
9            *ip = *rhs.ip;
10           return *this;
11       }
12   private:
13       C(const C&);
14       int* ip;
15   };

修正例 1 では、ip がポイントする動的メモリは新しい値に割り当てられる前に行 7 で解放されます。

脆弱コード例 2

1    class counted {
2    public:
3        counted() { counter = 1; }
4        void addRef() { counter++; }
5        void decRef() { counter--; if (counter == 0) delete this; }
6        /* other methods */
7    private:
8        int counter;
9        /* other members */
10   };
11
12   class C {
13   public:
14       C() { cp = new counted; }
15       ~C() { cp->decRef(); }
16       C& operator=(const C& rhs) {
17           if (this == &rhs) return *this;
18           cp = rhs.cp;    // CL.MLK.ASSIGN reported
19           cp->addRef();
20           return *this;
21       }
22   private:
23       C(const C&);
24       counted* cp;
25   };

この例では、cp がポイントするメモリのリファレンスカウンターは上書きする前に減分されません。その結果メモリリークにつながる可能性があり、Klocwork によって CL.MLK.ASSIGN とレポートされます。

修正コード例 2

1    class counted {
2    public:
3        counted() { counter = 1; }
4        void addRef() { counter++; }
5        void decRef() { counter--; if (counter == 0) delete this; }
6        /* other methods */
7    private:
8        int counter;
9        /* other members */
10   };
11
12   class C {
13   public:
14       C() { cp = new counted(); }
15       ~C() { cp->decRef(); }
16       C& operator=(const C& rhs) {
17           if (this == &rhs) return *this;
18           cp->decRef();
19           cp = rhs.cp;
20           cp->addRef();
21           return *this;
22       }
23   private:
24       C(const C&);
25       counted* cp;
26   };          

これでリファレンスカウンターは減分され、欠陥のレポートはありません。

拡張機能

このチェッカーは、Klocwork knowledge base (ナレッジベース) を利用して拡張できます。詳細については、C/C++ 解析のチューニングを参照してください。