An improper value was passed to a memory deallocation routine.
This error indicates that the value being passed to a memory deallocation routine did not come from a call to the matching memory allocation routine. There are two common forms of this error. The first is an attempt to free something that was not allocated, such as the address of a static variable or a string literal. The second is an attempt to pass a value obtained from the allocation routine of one memory allocator to the deallocation routine of another memory allocator. For example, a value obtained from "malloc" must be deallocated with "free", not "delete."
C++ has two forms of delete: "delete" and "delete []", the array deallocator. The difference is only significant when freeing an array of class objects that have a non-trivial destructor. In this case, the array delete deallocator calls the destructor for each object in the array, while the ordinary delete deallocator does not. Calling the ordinary deallocator instead of the array deallocator in such cases effectively violates C++ object semantics and can result in memory leaks or other errors.
As a general rule of thumb, an object obtained from an array allocator should always be deallocated with the array deallocator, even if it is safe to use the ordinary deallocator. This protects against future errors if the class is modified in such a way that the destructor becomes non-trivial. However, this diagnostic is not emitted in cases where the ordinary deallocator is used to release arrays of simple objects.
It is good practice to avoid using a single pointer variable to hold values obtained from different allocators at different times, as this creates confusion about how that storage should be properly deallocated.
ID |
Observation |
Description |
---|---|---|
1 |
Deallocation site |
The place the inappropriate value is freed |
#include <stdlib> #include <new> // A class with non-trivial destructor class NonTrivial { private: char *m_string; public: // Constructor allocates m_string NonTrivial() { m_string = new char[10]; } // Destructor frees m_string ~NonTrivial() { delete m_string; } // Copy constructor doesn't copy m_string field NonTrivial(const NonTrivial & source) : m_string(new char[10]) { for (int i = 0; i < 10; i++) { m_string[i] = source.m_string[i]; } } // Assignment operator doesn't assign m_string field NonTrivial& NonTrivial::operator=(const NonTrivial & source) { for (int i = 0; i < 10; i++) { m_string[i] = source.m_string[i]; } return *this; } }; char c; NonTrivial glob; int main(int argc, char **argv) { NonTrivial *p1 = new NonTrivial[10]; NonTrivial *p2 = new NonTrivial(glob); // copy constructor char *p3 = "abcd"; char *p4 = &c; *p1 = *p2; *p4 = *p3; // assignment operator delete p1; // bad: should use delete [] free(p2); // bad: should use delete free(p3); // bad: not allocated object free(p4); // bad: not allocated object delete &c; // bad: not allocated object }
Copyright © 2010, Intel Corporation. All rights reserved.