メインコンテンツ

MISRA C:2023 Rule 18.6

The address of an object with automatic or thread-local storage shall not be copied to another object that persists after the first object has ceased to exist

R2024a 以降

説明

ルール定義

The address of an object with automatic storage or thread-local shall not be copied to another object that persists after the first object has ceased to exist 1 .

根拠

オブジェクトのアドレスはオブジェクトの有効期間が切れたときに確定できなくなります。確定できないアドレスの使用は未定義の動作になります。

Polyspace 実装

ローカル変数またはスレッド ローカル変数を指すポインターが変数のスコープをエスケープする場合、Polyspace® はこのルールの違反を報告します。次に例を示します。

  • 関数が、ローカル変数を指すポインターを返す。

  • 関数が代入 globPtr = &locVar を実行する。globPtr はグローバル ポインター変数、locVar はローカル変数です。

  • 関数が代入 *paramPtr = &locVar を実行する。paramPtr は関数パラメーター (つまり int** ポインターなど)、locVar はローカルの int 変数です。

  • スレッド ローカル変数のアドレスは、グローバル ポインターに代入されます。

Polyspace はこのルールを、関数 alloca を使用して割り当てられるメモリに対して適用し、静的ローカル変数は無視します。Polyspace は、関数定義に含まれるローカル オブジェクトは同じスコープ内にあると仮定します。

トラブルシューティング

ルール違反を想定していてもその違反が表示されない場合、コーディング規約違反が想定どおりに表示されない理由の診断を参照します。

すべて展開する


        
void func2(int *ptr) {
    *ptr = 0;
}

int* func1(void) {
    int ret = 0; //Noncompliant
    return &ret ;
}
void main(void) {
    int* ptr = func1() ;
    func2(ptr) ;
}

この例では、func1 はローカル変数 ret を指すポインターを返します。

main では、ptr はローカル変数のアドレスを指します。ret のスコープは func1 に制限されているため、func2 内で ptr がアクセスされると、そのアクセスは無効になります。

char *func(void) {
	char local_auto; /* Noncompliant*/
	return &local_auto ;  /* &local_auto is indeterminate*/
}

この例では、local_auto はローカル変数であるため、関数が変数を返した後、local_auto のアドレスは確定できません。Polyspace は違反を報告します。


void h(void){
    static unsigned short *q;
    
    unsigned short x =0u; //Noncompliant
    q = &x;  
}

この例では、関数 h はローカル変数 x のアドレスを静的変数 q に格納します。静的変数 q の有効期間は、ローカル変数 x の有効期間が終了した後も継続します。xq にコピーすることはこのルールに準拠していないため、Polyspace は変数 x にフラグを設定します。

この例では、スレッド ローカル変数 thread_local_var のアドレスがグローバル ポインター ptr_global_var に代入されます。その後、関数 thread_function がスレッド myThread で呼び出されます。myThread が終了した後、変数 thread_local_var はスコープから外れ、ポインター ptr_global_var は破棄されたオブジェクトを指します。Polyspace は、このルールの違反を報告します。

#include <stdint.h>
#include <threads.h>
#include <stdlib.h>

_Thread_local int32_t thread_local_var = 0;
int* ptr_global_var;

void* thread_function(void* arg) {
    thread_local_var = (int32_t)arg;
    ptr_global_var = &thread_local_var;         /* Noncompliant */
}

void call_thread_function(void) {
    thrd_t myThread;

    ptr_global_var = &thread_local_var;
    thrd_create(&myThread, thread_function, (void*)1L);
    thrd_join(myThread, NULL);

    *ptr_global_var = 2; /* Bad memory access */
}

チェック情報

グループ: ポインターと配列
カテゴリ: 必要
AGC カテゴリ: 必要

バージョン履歴

R2024a で導入

すべて展開する


1 All MISRA coding rules and directives are © Copyright The MISRA Consortium Limited 2021.

The MISRA coding standards referenced in the Polyspace Bug Finder™ documentation are from the following MISRA standards:

  • MISRA C:2004

  • MISRA C:2012

  • MISRA C:2023

  • MISRA C++:2008

  • MISRA C++:2023

MISRA and MISRA C are registered trademarks of The MISRA Consortium Limited 2021.