Main Content

MISRA C++:2023 Rule 6.8.2

A function must not return a reference or a pointer to a local variable with automatic storage duration

Since R2024b

Description

Rule Definition

A function must not return a reference or a pointer to a local variable with automatic storage duration.

Rationale

Automatic local variables of a function are destroyed when the function returns to its calling function. If the function returns a reference or pointer to such a variable, then the program can attempt to use the variable after its destruction, which leads to undefined behavior. Specifically, this rule applies when a function returns:

  • A pointer or reference to a parameter that is passed by value

  • A lambda that captures a local variable by reference

  • A lambda that captures the address of a local variable

For this rule, a throw statement that is not caught within the function is considered a return from the function.

This rule and MISRA C++:2023 Rule 6.8.3 detect trivial and specific instances of potentially danging pointers and references. Other cases are covered by Rule 6.8.1.

Polyspace Implementation

Polyspace® reports a violation of this rule if any of these conditions are true:

  • A function returns a pointer or reference to a local nonstatic variable.

  • A function returns a lambda that captures a local nonstatic variable by reference or by pointer.

  • A function throws a pointer or reference to a local variable but does not catch the thrown object within the function body.

Troubleshooting

If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

In this example, the functions foo(), bar(), and bar2() return pointers or references to local variables. Polyspace reports violations on these functions.

#include <cstdint>

int32_t* foo()
{
	int32_t var = 99;
	return &var; //Noncompliant
}

int32_t& bar()
{
	int32_t var = 99;
	return var; //Noncompliant
}

int32_t& bar2(int32_t input)
{
	input++;
	return input; //Noncompliant
}

int32_t * foo2()
{
    int32_t  var = 341;
    int32_t *p2var = &var;

    return p2var; //Compliant
}

In foo2(), the pointer p2var is a potential dangling pointer but this rule does not apply. This function violates rule 6.8.1.

In this example, the functions foo() and bar() return lambda objects that capture local variables by reference and by address, respectively. Polyspace reports violations of this rule for these functions.

#include <cstdint>
auto foo()
{
    int32_t var { 341 };
    return [&var]() {}; //Noncompliant
}

auto bar()
{
    int32_t var { 341 };
    return [ y = &var]() {}; //Noncompliant
}

auto func()
{
    int32_t var { 341 };
    return [ = ]() {}; //Compliant
}

The function func() returns a lambda object that captures the local variables by copy. This function is compliant with this rule.

In this example, the function foo() throws a local variable by reference but does not catch the thrown object. Polyspace reports a violation of this rule.

#include <cstdint>
void foo()
{
	int32_t error = 0;
	throw &error; // Noncompliant
}

void bar()
{
	try
	{
		int32_t error = 2;
		throw &error; //Compliant
	}
	catch(...)
	{
	}
}

The function bar() throws a local variable by reference and then catches the thrown object within the function body. Throwing a local variable by reference and then catching it within the same function is not a violation of this rule because the thrown reference cannot become a dangling reference.

Check Information

Group: Basic concepts
Category: Mandatory

Version History

Introduced in R2024b