メインコンテンツ

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

CERT C: Rule MEM34-C

Only free memory allocated dynamically

説明

ルール定義

動的に割り当てられたメモリのみを解放します。1

Polyspace 実装

ルール チェッカーは以下の問題をチェックします。

  • ポインターの無効な解放

  • ポインターの無効な再割り当て

すべて展開する

問題

ポインターの無効な解放は、関数 free を使用して解放されたメモリのブロックが、以前に malloccalloc または realloc を使用して割り当てられていなかった場合に発生します。

リスク

関数 free はヒープに割り当てられたメモリのブロックを解放します。以前に割り当てていないヒープ上の位置にアクセスしようとすると、セグメンテーション違反が発生する可能性があります。

この問題により、コーディング エラーが強調表示される場合があります。たとえば、関数 free を別のポインターに対して使用する必要があった場合です。

修正方法

ほとんどの場合、free ステートメントを削除することによって問題を修正できます。malloc または calloc を使用してポインターにヒープのメモリが割り当てられていない場合、このポインターを解放する必要はありません。単に必要に応じてポインターを再利用できます。

この問題によって、間違ったポインターに対して free または malloc を使用するなどのコーディング エラーが明らかになった場合は、そのエラーを修正します。

new 演算子で割り当てられたメモリを解放するために関数 free を使用したことが原因で問題が発生している場合は、関数 freedelete 演算子に置き換えます。

例 - ポインターの無効な解放エラー
#include <stdlib.h>

void Assign_Ones(void) 
{
  int p[10];
  for(int i=0;i<10;i++)
     *(p+i)=1; 
 
  free(p);    //Noncompliant
  /* Defect: p does not point to dynamically allocated memory */
}

ポインター p は、関数 free を使用して割り当て解除されています。しかし、p は動的に割り当てられていないメモリの場所を指しています。

修正 — ポインターの割り当て解除を削除

配列 p の要素数がコンパイル時にわかっている場合、1 つの修正方法として、ポインター p の割り当て解除を削除することができます。

#include <stdlib.h>

void Assign_Ones(void)
 {
  int p[10];
  for(int i=0;i<10;i++)
     *(p+i)=1;   
  /* Fix: Remove deallocation of p */
 }
修正 — ポインターを割り当てる

配列 p の要素数がコンパイル時にわかっていない場合、1 つの修正方法として、配列 p に動的にメモリを割り当てることができます。

#include <stdlib.h>

void Assign_Ones(int num) 
{
  int *p;
  /* Fix: Allocate memory dynamically to p */
  p=(int*) calloc(10,sizeof(int)); 
  for(int i=0;i<10;i++)
     *(p+i)=1; 
  free(p); 
}
問題

"ポインターの無効な再割り当て" は、関数 realloc を使用して再割り当てされたメモリのブロックが、以前に malloc または calloc を使用して割り当てられていなかった場合に発生します。

リスク

動的に割り当てられていないメモリのブロックの再割り当ては、未定義動作につながる可能性があります。

この問題により、コーディング エラーが強調表示される場合があります。たとえば、関数 realloc を別のポインターに対して使用する必要があった場合です。

修正方法

メモリのブロックを再割り当てする場合は、最初に、それが動的に割り当てられていることを確認してください。

例 – 静的に割り当てられたメモリの再割り当て
#include <stdlib.h>
  
#define SIZE 256

void reshape(int isSpaceAvailable) {
  char buf[SIZE];
  char *newBuf;
  newBuf = (char *)realloc(buf, 2 * SIZE); //Noncompliant
  
  if (newBuf == NULL) {
    /* Handle error */
  }
}

この例では、バッファー buf が動的に割り当てられていません。そのため、buf を再割り当てすると、未定義動作が発生します。

例 – 静的に割り当てられたメモリの再割り当て

再割り当てするバッファーが以前に動的に割り当てられたメモリであることを確認してください。

#include <stdlib.h>
  
#define SIZE 256

void reshape(void){
  char *buf;
  char *newBuf;
  buf = (char*)malloc(SIZE *sizeof(char));
  newBuf = (char *)realloc(buf, 2 * SIZE);
  
  if (newBuf == NULL) {
    /* Handle error */
  }
  free(newBuf);
}

チェック情報

グループ: 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.