Professional C__ - Marc Gregoire [380]
char* ch = new char;
SuperSmartPointer SuperSmartPointer One solution to this problem is to make the reference map a global variable, though globals are often frowned upon. Another solution would be to wrap the map in a non-template singleton class, perhaps called MapManager, which is referenced by the SuperSmartPointer template classes. The singleton pattern is discussed in Chapter 29. The other issue with this implementation is that it is not thread safe. As Chapter 22 explains, threads are a new feature of C++11. Threads are very common in modern programming so you should be aware of thread safety. Access to the static map should be protected by a lock so that concurrent additions and deletions do not conflict with each other. Chapter 22 gives you all the details about how to protect access to data in multithreaded programs. Remember, the SuperSmartPointer class is given here for illustrative purposes only. You should use the standard C++11 shared_ptr or unique_ptr in your programs unless you have a valid reason and you know exactly what you are doing. COMMON MEMORY PITFALLS Underallocating Strings The most common problem with C-style strings is underallocation. In most cases, this arises when the programmer fails to allocate an extra character for the trailing '\0' sentinel. Underallocation of strings also occurs when programmers assume a certain fixed maximum size. The basic built-in string functions will not adhere to a fixed size — they will happily write off the end of the string into uncharted memory. The following code reads data off a network connection and puts it in a C-style string. This is done in a loop because the network connection only receives a small amount of data at a time. On each loop, getMoreData() is called, which returns a pointer to dynamically allocated memory. When nullptr is returned from getMoreData(), all of the data has been received. char buffer[1024] = {0}; // Allocate a whole bunch of memory. while (true) { char* nextChunk = getMoreData(); if (nextChunk == nullptr) { break; } else { strcat(buffer, nextChunk); // BUG! No guarantees against buffer overrun! delete [] nextChunk; } } There are three ways to resolve the possible underallocation problem. In decreasing order of preference, they are: 1. Use C++-style strings, which will handle the memory associated with concatenation on your behalf. 2. Instead of allocating a buffer as a global variable or on the stack, allocate it on the heap. When there is insufficient space left, allocate a new buffer large enough to hold at least the current contents plus the new chunk, copy the original buffer into the new buffer, append the new contents, and delete the original buffer. 3. Create a version of getMoreData() that takes a maximum count (including the '\0' character) and will return no more characters than that; then track the amount of space left and the current position in the buffer. Memory Leaks Finding and fixing memory leaks can be one of the more frustrating parts of programming in C or C++. Your program finally works and appears to give the correct results. Then, you start
It is difficult to pinpoint the exact situations that can lead to a memory-related bug. Every memory leak or bad pointer has its own nuances. There is no magic bullet for resolving memory issues, but there are several common categories of problems and some tools you can use to detect and resolve them.