Main Content

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

Since R2024a

Description

Rule Definition

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.

Rationale

The address of an object becomes indeterminate when the lifetime of that object expires. Any use of an indeterminate address results in undefined behavior.

Polyspace Implementation

Polyspace® reports a violation of this rule when a pointer to a local variable or thread local leaves the scope of the variable. For instance:

  • A function returns a pointer to a local variable.

  • A function performs the assignment globPtr = &locVar. globPtr is a global pointer variable and locVar is a local variable.

  • A function performs the assignment *paramPtr = &locVar. paramPtr is a function parameter that is, for instance, an int** pointer and locVar is a local int variable.

  • The address of a thread local variable is assigned to a global pointer.

Polyspace applies this rule on memory allocated using the alloca function and ignores static local variables. Polyspace assumes that the local objects within a function definition are in the same scope.

Troubleshooting

If you expect a rule violation but do not see it, refer to Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

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

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

In this example, func1 returns a pointer to local variable ret.

In main, ptr points to the address of the local variable. When ptr is accessed in func2, the access is illegal because the scope of ret is limited to func1,

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

In this example, because local_auto is a local variable, after the function returns, the address of local_auto is indeterminate. Polyspace reports a violation.

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

In this example, the function h stores the address of a local variable x in the a static variable q. The lifetime of the static variable q persists after the lifetime of the local variable x ends. Copying x into q is noncompliant with this rule and Polyspace flags the variable x.

In this example, address of the thread local variable thread_local_var is assigned to the global pointer ptr_global_var. The function thread_function is then invoked on the thread myThread. After myThread terminates, the variable thread_local_var goes out of scope and the pointer ptr_global_var points to a destroyed object. Polyspace reports a violation of this rule.

#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 */
}

Check Information

Group: Pointers and Arrays
Category: Required
AGC Category: Required

Version History

Introduced in R2024a

expand all