The result of applying delete to a pointer that holds the address of a valid object in the heap is to change the status of that heap memory from "in use" to "available." After delete has been applied to a pointer, the state of that pointer itself is undefined. The pointer may or may not still store the address of that deleted memory, so a second application of delete to the same pointer may cause run-time problemspossibly heap corruption.
In general, the compiler cannot detect attempts to apply delete repeatedly to the same object, especially if that piece of memory (or a part thereof) has since been reallocated. To help avoid the very undesirable consequences of a repeated delete, it is good practice to assign NULL to a pointer immediately after it has been deleted.
If delete is applied to a null pointer, there is no action and no error.
Applying delete to a non-null pointer that was not returned by new produces undefined results. In general, the compiler will not be able to determine whether the pointer was or was not returned by new, so undefined run-time behavior can result. Bottom line: It is the programmer's responsibility to use delete correctly.
One of the richest sources of run-time errors is the production of memory leaks. A memory leak is produced when a program causes memory to be allocated and then loses track of that memory so that it can neither be accessed nor deleted. An object that is not properly deleted will occupy memory until the process terminates.
Some programs (e.g., operating systems) stay active for a long time. Suppose such a program contains a frequently executed routine that produces a memory leak each time it is run. The heap will gradually become perforated with blocks of inaccessable, undeleted memory. At some point a routine that needs a substantial amount of contiguous dynamic memory may have its request denied. If the program was not expecting an event like that, it may not be able to continue.
The operators new and delete give the C++ programmer increased power as well as increased responsibility.
Here is some sample code that illustrates a memory leak. After defining a couple of pointers, memory will look a little like Figure 22.1.
int* ip = new int; // allocate space for an int int* jp = new int(13); // allocate and initialize cout << ip << ' ' << jp << endl;
Figure 22.1. Initial values of memory
Now we add one more line of code.
jp = new int(3); // reassign the pointer - MEMORY LEAK!!
After executing the single line above, our memory looks like Figure 22.2.
Figure 22.2. Memory after leak
Example 22.3. src/pointers/pathology/pathologydemo1.cpp
#include using namespace std; int main() { int* jp = new int(13); <-- 1 cout << jp << ' ' << *jp << endl; delete jp; delete jp; <-- 2 jp = new int(3); <-- 3 cout << jp << ' ' << *jp << endl; jp = new int(10); <-- 4 cout << jp << ' ' << *jp << endl; int* kp = new int(17); cout << kp << ' ' << *kp << endl; return 0; } Output: OOP> g++ pathologydemo1.cpp OOP> ./a.out 0x8049e08 13 0x8049e08 3 0x8049e08 10 Segmentation fault OOP>
|
In Example 22.3, we deleted the pointer jp twice. The second deletion is a serious error but the compiler did not catch it. That error corrupted the heap, made any further memory allocation impossible, and made the behavior of the program beyond that point undefined. For example, notice that when we attempted to produce a memory leak by reassigning the pointer jp, we did not get any new memory. When we attempted to introduce another pointer variable we got a segmentation fault. This is all undefined behavior and may be different on another platform or with another compiler.
Part I: Introduction to C++ and Qt 4
C++ Introduction
Classes
Introduction to Qt
Lists
Functions
Inheritance and Polymorphism
Part II: Higher-Level Programming
Libraries
Introduction to Design Patterns
QObject
Generics and Containers
Qt GUI Widgets
Concurrency
Validation and Regular Expressions
Parsing XML
Meta Objects, Properties, and Reflective Programming
More Design Patterns
Models and Views
Qt SQL Classes
Part III: C++ Language Reference
Types and Expressions
Scope and Storage Class
Statements and Control Structures
Memory Access
Chapter Summary
Inheritance in Detail
Miscellaneous Topics
Part IV: Programming Assignments
MP3 Jukebox Assignments
Part V: Appendices
MP3 Jukebox Assignments
Bibliography
MP3 Jukebox Assignments