メインコンテンツ

ISO/IEC TS 17961 [uninitref]

Referencing uninitialized memory

説明

ルール定義

未初期化のメモリの参照。1

Polyspace 実装

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

  • 未初期化ポインター

  • 未初期化値へのポインターが定数ポインターに変換

  • 未初期化変数

チェッカーの拡張

チェッカーは次の方法で拡張できます。

すべて展開する

問題

未初期化ポインターは、デリファレンスの前にポインターにアドレスが割り当てられていない場合に発生します。

リスク

ポインターにアドレスが明示的に割り当てられていない場合、そのポインターは予測できない位置を指します。

修正方法

修正方法は欠陥の根本原因によって異なります。たとえば、アドレスをポインターに割り当てたが、その割り当てに到達不能である場合があります。

多くの場合、結果の詳細には欠陥につながる一連のイベントが表示されます。そのシーケンス内のどのイベントについても修正を実装できます。結果の詳細にイベント履歴が表示されない場合は、ソース コード内で右クリック オプションを使用して逆のトレースを行い、これまでの関連するイベントを確認できます。Polyspace デスクトップ ユーザー インターフェイスでの Bug Finder の結果の解釈も参照してください。

以下の修正例を参照してください。ポインターを宣言するときはポインターを NULL に初期化することをお勧めします。

問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。

例 - 未初期化ポインター エラー
#include <stdlib.h>

int* assign_pointer(int* prev)
{
    int j = 42;
    int* pi;

    if (prev == NULL) 
      {
        pi = (int*)malloc(sizeof(int));
        if (pi == NULL) return NULL;
      }

    *pi = j;                    
    /* Defect: Writing to uninitialized pointer */

    return pi;
}

prevNULL でない場合、ポインター pi にはアドレスが割り当てられません。しかし、prevNULL かどうかにかかわりなく、pi はすべての実行パスでデリファレンスされます。

修正 — すべての実行パスでポインターを初期化

1 つの修正方法として、prevNULL でない場合に pi にアドレスを割り当てることができます。

#include <stdlib.h>

int* assign_pointer(int* prev)
{
    int j = 42;
    int* pi;

    if (prev == NULL) 
       {
        pi = (int*)malloc(sizeof(int));
        if (pi == NULL) return NULL;
       } 
    /* Fix: Initialize pi in branches of if statement  */
    else 
        pi = prev;              
    

    *pi = j;

    return pi;
}
問題

未初期化値へのポインターが定数ポインターに変換は、まだ値を含まないアドレスが定数へのポインター (const int*const char* など) に割り当てられる場合に発生します。

リスク

定数へのポインターは、プログラム内で後で変更されない値を格納します。未初期化変数のアドレスをポインターに割り当てると、このポインターはプログラムの残りに対するゴミ値をもつアドレスを指します。

修正方法

定数へのポインターに変数のアドレスを割り当てる前に、その変数を初期化します。

例 - 未初期化値へのポインターが定数ポインターに変換されるエラー
#include<stdio.h>

void Display_Parity()
 {
  int num,parity;
  const int* num_ptr = &num;  
  /* Defect: Address &num does not store a value */

  printf("Enter a number\n:");
  scanf("%d",&num);

  parity=((*num_ptr)%2);
  if(parity==0)
    printf("The number is even.");
  else
    printf("The number is odd.");

 }

num_ptr は定数へのポインターとして宣言されています。しかし、num_ptr にアドレス &num が割り当てられるとき、変数 num には値が含まれていません。

修正 — ポインターへの割り当て前にアドレスに値を保存

1 つの修正方法として、&numnum_ptr に割り当てられる前に、ユーザーから num の値を取得することができます。

#include<stdio.h>

void Display_Parity()
 {
  int num,parity;
  const int* num_ptr;

  printf("Enter a number\n:");
  scanf("%d",&num);

 /* Fix: Assign &num to pointer after it receives a value */ 
  num_ptr=&num;                     
  parity=((*num_ptr)%2);
  if(parity==0)
    printf("The number is even.");
  else
    printf("The number is odd.");
 }

scanf ステートメントは値を &num に保存します。値が保存されたら、&numnum_ptr に適正に割り当てられます。

問題

未初期化変数は、変数の値が読み取られる前にその変数が初期化されていない場合に発生します。

リスク

変数が明示的に初期化されていない場合、変数値は予測できません。変数が特定の値をもつことは期待できません。

修正方法

修正方法は欠陥の根本原因によって異なります。たとえば、値を変数に割り当てたがその割り当てに到達不能であるか、条件付きステートメントの 2 つの分岐のいずれかで値を変数に割り当てた可能性があります。到達不能コードまたは割り当ての欠落を修正します。

多くの場合、結果の詳細には欠陥につながる一連のイベントが表示されます。そのシーケンス内のどのイベントについても修正を実装できます。結果の詳細にイベント履歴が表示されない場合は、ソース コード内で右クリック オプションを使用して逆のトレースを行い、これまでの関連するイベントを確認できます。Polyspace デスクトップ ユーザー インターフェイスでの Bug Finder の結果の解釈も参照してください。

以下の修正例を参照してください。宣言時に変数を初期化することをお勧めします。

問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。

例 - 未初期化変数エラー
int get_sensor_value(void)
{
    extern int getsensor(void);
    int command;
    int val;

    command = getsensor();
    if (command == 2) 
      {
        val = getsensor();
      }

    return val;              
    /* Defect: val does not have a value if command is not 2 */
}

command が 2 でない場合、変数 val には値が割り当てられません。この場合、関数 get_sensor_value の戻り値は未定です。

修正 — 宣言に際しての初期化

1 つの修正方法として、一部の実行パスで初期化が回避されることのないように、宣言時に val の初期化を行います。

int get_sensor_value(void)
{
    extern int getsensor(void);
    int command;
    /* Fix: Initialize val */
    int val=0;

    command = getsensor();
    if (command == 2) 
      {
        val = getsensor();
      }

    return val;              
 }

val には初期値 0 が割り当てられます。command が 2 と等しくない場合、関数 get_sensor_value はこの値を返します。

チェック情報

決定可能性:決定不可能

バージョン履歴

R2019a で導入


1 Extracts from the standard "ISO/IEC TS 17961 Technical Specification - 2013-11-15" are reproduced with the agreement of AFNOR. Only the original and complete text of the standard, as published by AFNOR Editions - accessible via the website www.boutique.afnor.org - has normative value.