...
The following Standard Template Library functions are guaranteed to leave the moved-from object in a well-specified state.
| Type | Functionality | Moved-from State |
|---|---|---|
std::unique_ptr | Move construction, Move assignment, "Converting" move construction, "Converting" move assignment ( |
likewise for std::unique_ptr for array objects with a runtime length) | The moved-from object is guaranteed to refer to a null pointer value, per [unique.ptr], paragraph 4 [ISO/IEC 14882-2014]. | |
std::shared_ptr | Move construction, Move assignment, | The moved-from object shall be "empty," per [util.smartptr.shared.const], paragraph 22 and [util.smartptr.shared.assign], paragraph 4. |
std::shared_ptr | Move construction, Move assignment from a std::unique_ptr | The moved-from object is guaranteed to refer to a null pointer value, per [util.smartptr.shared.const], paragraph 29 and [util.smartptr.shared.assign], paragraph 6. |
std::weak_ptr | Move construction, Move assignment, "Converting" move construction, "Converting" move assignment | The moved-from object shall be "empty," per [util.smartptr.weak.const], paragraph 8, and [util.smartptr.weak.assign], paragraph 4. |
std::basic_ios | move() | The moved-from object is still left in an unspecified state, except that rdbuf() shall return the same value as it returned before the move, and tie() shall return 0, per [basic.ios.members], paragraph 20. |
std::basic_filebuf | Move constructor, Move assignment | The moved-from object is guaranteed to reference no file; other internal state is also affected, per [filebuf.cons], paragraphs 3 and 4, and [filebuf.assign], paragraph 1. |
std::thread | Move constructor, Move assignment | The result from calling get_id() on the moved-from object is guaranteed to remain unchanged; otherwise the object is in an unspecified state, per [thread.thread.constr], paragraph 11 and [thread.thread.assign], paragraph 2. |
std::unique_lock | Move constructor, Move assignment | The moved-from object is guaranteed to be in its default state, per [thread.lock.unique.cons], paragraphs 21 and 23. |
std::shared_lock | Move constructor, Move assignment | The moved-from object is guaranteed to be in its default state, per [thread.lock.shared.cons], paragraphs 21 and 23. |
std::promise | Move constructor, Move assignment | The moved-from object is guaranteed not to have any shared state, per [futures.promise], paragraphs 6 and 8. |
std::future | Move constructor, Move assignment | Calling valid() on the moved-from object is guaranteed to return false, per [futures.unique_future], paragraphs 8 and 11. |
std::shared_future | Move constructor, Move assignment, "Converting" move constructor, "Converting" move assignment | Calling valid() on the moved-from object is guaranteed to return false, per [futures.shared_future], paragraphs 8 and 11. |
std::packaged_task | Move constructor, Move assignment | The moved-from object is guaranteed not to have any shared state, per [future.task.members], paragraphs 7 and 8. |
Several generic standard template library (STL) algorithms, such as std::remove() and std::unique(), remove instances of elements from a container without shrinking the size of the container. Instead, these algorithms return a ForwardIterator to indicate the partition within the container after which elements are no longer valid. The elements in the container that precede the returned iterator are valid elements with specified values; whereas the elements that succeed the returned iterator are valid but have unspecified values. Accessing unspecified values of elements iterated over results in unspecified behavior. Frequently, the erase-remove idiom is used to shrink the size of the container when using these algorithms.
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <iostream>
#include <string>
void g(std::string &&v) {
std::cout << v << std::endl;
}
void f() {
std::string s;
for (unsigned i = 0; i < 10; ++i) {
s.append(1, static_cast<char>('0' + i));
g(std::move(s));
}
} |
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <iostream>
#include <string>
void g(std::string &&v) {
std::cout << v << std::endl;
}
void f() {
for (unsigned i = 0; i < 10; ++i) {
std::string s(1, static_cast<char>('0' + i));
g(std::move(s));
}
} |
...
The state of a moved-from object is generally valid, but unspecified. Relying on unspecified values can lead to abnormal program termination as well as data integrity violations.
Rule | Severity | Likelihood | Detectable |
|---|
Repairable | Priority | Level |
|---|---|---|
EXP63-CPP | Medium | Probable |
Yes | No | P8 | L2 |
Automated Detection
Tool | Version | Checker | Description |
|---|
| CodeSonar |
| LANG.MEM.NPD | Null Pointer Dereference | ||||||
| Helix QAC |
| DF4701, DF4702, DF4703 | |||||||
| CERT_CPP-EXP63-a | Do not rely on the value of a moved-from object | |||||||
| Polyspace Bug Finder |
| CERT C++: EXP63-CPP | Checks for read operations that reads the value of a moved-from object (rule fully covered) | ||||||
| PVS-Studio |
| V1030 |
Related Vulnerabilities
Search for other vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Bibliography
| [ISO/IEC 14882-2014] | Subclause 17.6.5.15, "Moved-from State of Library Types" |
...
...