Start here

Home
About Klocwork
What's new
Fixed issues
Release notes
Installation

Reference

C/C++ checkers
Java checkers
C# checkers
MISRA C 2004 checkers
MISRA C++ 2008 checkers
MISRA C 2012 checkers
MISRA C 2012 checkers with Amendment 1
Commands
Metrics
Troubleshooting
Reference

Product components

C/C++ Integration build analysis
Java Integration build analysis
Desktop analysis
Refactoring
Klocwork Static Code Analysis
Klocwork Code Review
Structure101
Tuning
Custom checkers

Coding environments

Visual Studio
Eclipse for C/C++
Eclipse for Java
IntelliJ IDEA
Other

Administration

Project configuration
Build configuration
Administration
Analysis performance
Server performance
Security/permissions
Licensing
Klocwork Static Code Analysis Web API
Klocwork Code Review Web API

Community

View help online
Visit RogueWave.com
Klocwork Support
Rogue Wave Videos

Legal

Legal information

CL.FFM.COPY

Freeing freed memory due to missing copy constructor

Class-level checkers produce recommendations based on Scott Meyer's rules for effective C++ class construction.

CL.FFM.COPY is based on Scott Meyer's Item 11: Declare a copy constructor and an assignment operator for classes with dynamically allocated memory. This checker looks for classes that contain dynamically allocated data members and don't define a copy constructor.

When there is no implementation of the copy constructor, the C++ compiler auto-generates a copy constructor wherever it is needed, but that compiler-provided implementation is always explicitly shallow.

Copying an object, either through initialization or using a pass-by-value function call, can result in two objects referencing a single dynamically allocated data member if the copy is not explicitly coded to manage those data members. A shallow copy operation in which pointers are simply copied by value results in a pair of objects both pointing to the same underlying heap memory. Any operation performed on that heap memory will affect both objects that are maintaining references to it. This can lead to synchronization problems in multi-threaded applications and unexpected results in all types of programs.

The situation this particular checker references is the potential for freeing already freed memory, which occurs when two such objects sharing a common underlying allocation go out of scope.

Vulnerability and risk

In this situation, the first object to go out of scope will typically release all associated heap memory, including the buffer that is now shared with another object. When that second object goes out of scope, its attempt to free what it believes to be its own memory resources will result in access to already released memory, something that could corrupt the heap in a worst-case scenario.

Mitigation and prevention

To address the problem, always provide an explicit implementation of the assignment operator for classes that contain dynamically allocated data members, and always ensure that the assignment operator performs a deep copy of those data members.

Vulnerable code example

     
1    #include <iostream>
2    using namespace std;
3    class C{
4      char* data;
5      C& operator=(const C&) {return *this;}
6    public:
7      C() { data = new char[10]; }
8      ~C(){
9        cout << "Calling delete for " << (void *)data << endl;
10        delete[] data;
11      }
12    };
13    int main(){
14      C c1;
15      C c2 = c1;
16      return 1;
17    }


Output:

Calling delete for 0x602010
Calling delete for 0x602010

In this example, the copy constructor is called at line 15. Since 'C' doesn't define a copy constructor, the compiler generates one that copies all values from one instance to another. As a result, both 'c1.data' and 'c2.data' have the same value, and delete it twice when the destructors are called. In this case, CL.FFM.COPY has found a typical example of a class that contains dynamically allocated data members and doesn't define a copy constructor.

Fixed code example

To fix this problem, one of two different implementations can be used, depending on the situation.

Typically, a deep copy constructor should be defined:

1    class C{
// ...
2      C(const C& src){
3        data = new char[10];
4        memcpy(data, src.data, 10);
5      }
// ...
6    };

If the instances are not meant to be copied, the copy constructor should be declared as private:

1    class C{
// ...
2    private:
3      C(const C& src){ /* do not create copies */ }
// ...
4    };

Extension

This checker can be extended through the Klocwork knowledge base. See Tuning C/C++ analysis for more information.