Main Content

CERT C++: EXP63-CPP

Do not rely on the value of a moved-from object

Since R2021a

Description

Rule Definition

Do not rely on the value of a moved-from object.1

Polyspace Implementation

The rule checker checks for Reading the Value of a Moved-from Object.

Examples

expand all

Issue

This issue occurs when the value of a source object is read after its content is moved to a destination object by calling the std::move function explicitly. Polyspace® does not flag accessing the value of a moved-from object if:

  • The source object of an explicit move operation is of these types:

    • std::unique_ptr

    • std::shared_ptr

    • std::weak_ptr

    • std::basic_ios

    • std::basic_filebuf

    • std::thread

    • std::unique_lock

    • std::shared_lock

    • std::promise

    • std::future

    • std::shared_future

    • std::packaged_task

    These objects do not remain in an unspecified state after their state is moved explicitly.

  • The move operation is performed implicitly. For instance, the function std::remove might access the state of a source object after an implicit move operation. Polyspace does not flag it. A best practice is to avoid such operations and use safer alternatives that prevent accidental access, such as std::erase.

  • The source object is of a built-in base type, such as: int, enum, float, double, pointer, std::intptr_t, std::nullptr_t.

Risk

Because the state of a source object is generally unspecified after a move operation, it is unsafe to perform operations that rely on the state of the source object after a move operation. Accessing the state of the source object after a move operation might result in a data integrity violation, an unexpected value, or an illegal dereferencing of a pointer.

Fix

Avoid operations that might read a source object after its content is moved.

Example — Reading Value of Source Object After Calling std::move
#include<string>
#include<iostream>
void F1()
{
	std::string s1{"string"};
	std::string s2{std::move(s1)}; 
	// ...
	std::cout
	<<  // Noncompliant
	s1
	<< "\n";
	// value after move operation
}
void g(std::string v)
{
	std::cout << v << std::endl; 
}

void F3()
{
	std::string s;
	for (unsigned i = 0; i < 10; ++i) {
		s.append(1, static_cast<char>('0' + i));  //Noncompliant 
		g(std::move(s));
	}
}

  • In the function F1, the string s1 is explicitly moved to s2 by calling std::move. After the move operation, the function attempts to read s1. Polyspace flags this attempt of reading a source object after an explicit move.

  • In the function F3, the string s is explicitly moved and then it is read by the std::string::append function. Polyspace flags this attempt of reading a source object after an explicit move.

Correction — Read Values of Source Objects in Specified State
#include<string>
#include<iostream>
void F2()
{
	std::unique_ptr<std::int32_t> ptr1 = std::make_unique<std::int32_t>(0);
	std::unique_ptr<std::int32_t> ptr2{std::move(ptr1)};
	std::cout << ptr1.get() << std::endl; // Compliant by exception
}
void g(std::string v)
{
	std::cout << v << std::endl; 
}
void F4()
{
	for (unsigned i = 0; i < 10; ++i) {
		std::string s(1, static_cast<char>('0' + i)); // Compliant
		g(std::move(s));  
	}
}

  • In the function F2, the unique pointer ptr1 is explicitly moved to ptr2. Because the state of std::unique_ptr remains in a specified state after the move, reading a source unique pointer after an explicit move is compliant.

  • In the function F4, the string s is explicitly moved. In each iteration of the loop, s is initiated to specific content before the move operation is triggered. As a result, the state of s is specified before the object is accessed. This method of accessing the source object after a move operation is compliant with this rule.

Check Information

Group: Rule 02. Expressions (EXP)

Version History

Introduced in R2021a


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.