Expensive pass by value
Description
This defect occurs when you pass a parameter by value instead of by reference or pointer, but the parameter is unmodified and either:
The parameter is a non-trivially copyable type. For more on non-trivially copyable types, see is_trivially_copyable.
The parameter is a trivially copyable type that is above a certain size. For example, an object greater than
2 * sizeof(void *)
is more expensive to pass by value than by reference or pointer.
Polyspace® flags unmodified parameters that meet the preceding conditions even if the
parameters are not declared const
.
Polyspace raises no defect if:
The passed by value parameter is a move-only type. For instance,
std::unique_ptr
can be moved-from but cannot be copied.The passed by value parameter is modified.
The parameter is passed by value to a
virtual
overriding method in a derived class.In this instance, fixing the defect might require modifying the signature of the base class method which might not be possible for the owner of the derived class.
The parameter is passed by value to a
virtual
method in a base class and the parameter is non-const
.In this instance, if there are overriding methods in derived classes that modify their parameter, it might not be possible to properly update those methods if a fix is applied to the base class method.
Note that if the parameter is
const
, overriding methods in derived classes do not modify their parameters and applying a fix in the base class is safe. In this case, Polyspace reports an expensive pass by value defect.
For example, in the following code, Polyspace does not report a defect in these functions and methods:
The function
offset()
because its parameter is modified.The function
moveOnly()
because its parameter is a move-only type.Methods
D::parse_M
andD::print_M
because they arevirtual
overriding methods in a derived class.The method
Base::print_M
because it is avirtual
method in a base class with a non-const
parameter.
Polyspace does report a defect for Base::parse_M
because its parameter
is const
and non-trivially
copyable.
#include <string>
#include <memory>
#include <iostream>
typedef struct Buffer
{
unsigned char bytes[20];
int index;
} Buffer;
void offset(Buffer modifiedBuffer)
{
++modifiedBuffer.index;
}
void moveOnly(std::unique_ptr<Buffer> move_only_param);
// virtual methods example
class Base
{
public:
virtual void parse_M(const std::string msg);
virtual void print_M(std::string msg)
{
std::cout << "Base message: " << msg << "\n";
}
};
class D : public Base
{
public:
void parse_M(const std::string msg) override;
void print_M(std::string msg) override
{
std::cout << "Derived message: " << msg << "\n";
}
};
Risk
Passing a parameter by value creates a copy of the parameter which is inefficient if the
parameter is expensive to copy. Even if your intent is to pass by reference or pointer, you
might forget the const&
or const*
in your function
signature and inadvertently run an inefficient version of the function.
Fix
Convert the parameter to a const
pointer (const*
)
for C code, or to a const
reference (const&
) for
C++ code.
Performance improvements might vary based on the compiler, library implementation, and environment that you are using.
Examples
Result Information
Group: Performance |
Language: C | C++ |
Default: Off |
Command-Line Syntax:
EXPENSIVE_PASS_BY_VALUE |
Impact: Medium |
Version History
Introduced in R2020bSee Also
Find defects
(-checkers)
| Expensive return by
value
| Expensive copy in a range-based for
loop iteration
| Expensive local variable
copy
Topics
- Interpret Bug Finder Results in Polyspace Desktop User Interface
- Interpret Bug Finder Results in Polyspace Access Web Interface (Polyspace Access)
- Address Results in Polyspace User Interface Through Bug Fixes or Justifications
- Address Results in Polyspace Access Through Bug Fixes or Justifications (Polyspace Access)