メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

CERT C: Rule MEM31-C

Free dynamically allocated memory when no longer needed

説明

ルール定義

動的に割り当てられたメモリを使用する必要がなくなった場合は解放します。1

Polyspace 実装

ルール チェッカーは、"メモリ リーク" をチェックします。

すべて展開する

問題

メモリ リークは、malloccallocrealloc または new を通して割り当てられたメモリのブロックが解放されない場合に発生します。メモリが関数内で割り当てられる場合、以下の条件を満たせば欠陥は生じません。

  • 関数内で、free または delete を使用してメモリが解放される。

  • 関数が malloccallocrealloc または new によって割り当てられたポインターを返す。

  • 関数がグローバル変数またはパラメーターにポインターを格納する。

リスク

malloc などの動的メモリ割り当て関数はヒープ上のメモリを割り当てます。使用後にメモリを解放しないと、別の割り当てに使用できるメモリの量が減少します。メモリに制限がある組み込みシステムでは、プログラムの実行中でも、使用可能なヒープ メモリを使い果たす可能性があります。

修正方法

動的に割り当てられたメモリへのアクセスがあるスコープを確認します。このスコープの最後でメモリ ブロックを解放します。

メモリのブロックを解放するには、メモリの割り当て時に使用したポインターに対して関数 free を使用します。次に例を示します。

ptr = (int*)malloc(sizeof(int));
//...
free(ptr);

同じモジュール内のメモリは同じ抽象化レベルで割り当てと解放を行うことをお勧めします。次の例の場合、func はメモリの割り当てと解放を同じレベルで行っていますが、func2 はそうではありません。

void func() {
  ptr = (int*)malloc(sizeof(int));
  {
    //...
  }
  free(ptr);
}

void func2() {
  {
   ptr = (int*)malloc(sizeof(int));
   //...
  }
  free(ptr);
}
CERT-C Rule MEM00-C を参照してください。

例 - 関数の終了前に動的メモリが未解放
#include<stdlib.h>
#include<stdio.h>

void assign_memory(void)
{
    int* pi = (int*)malloc(sizeof(int));
    if (pi == NULL) 
        {
         printf("Memory allocation failed");
         return;
        }


    *pi = 42;
    /* Defect: pi is not freed */
} //Noncompliant

この例では、malloc によって pi が動的に割り当てられています。関数 assign_memory はメモリを解放せず、pi も返しません。

修正 — メモリを解放

1 つの修正方法として、pi が参照するメモリを関数 free を使用して解放することができます。関数 free は関数 assign_memory が終了する前に呼び出さなければなりません。

#include<stdlib.h>
#include<stdio.h>

void assign_memory(void)
{
    int* pi = (int*)malloc(sizeof(int));
    if (pi == NULL) 
        {
         printf("Memory allocation failed");
         return;
        }
    *pi = 42;

    /* Fix: Free the pointer pi*/
    free(pi);                   
}
修正 — 動的割り当てからポインターを返す

もう 1 つの修正方法は、ポインター pi を返すことです。pi を返すことにより、assign_memory を呼び出している関数が pi を使用してメモリ ブロックを解放できるようになります。

#include<stdlib.h>
#include<stdio.h>

int* assign_memory(void)
{
    int* pi = (int*)malloc(sizeof(int));
    if (pi == NULL) 
        {
            printf("Memory allocation failed");
            return(pi);
        }
    *pi = 42;

    /* Fix: Return the pointer pi*/
    return(pi);                   
}

チェック情報

グループ: Rule 08.メモリ管理 (MEM)

バージョン履歴

R2019a で導入


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.