Why Use Smart Pointers in C++?

There are a lot of mechanisms through which programmers can make their code cleaner, preserve memory, and still harness the power of the programming language in use. Such mechanisms almost always have demerits that are coupled with their merits. One such mechanism, used primarily in intermediate-level programming languages such as C++, is the Use of Smart Pointers which helps with automatic garbage collection and/or bounds checking. Smart pointers can save a programmer’s time and could further prevent a program from crashing or corrupting files on the system on which it is run due to memory leak or bounds wrapping/overwriting. A smart pointer is an abstract data type that simulates an ordinary pointer but still provides extra features mostly centered around memory management. This article will be based upon the use of pointers in C++.

A pointer in C/C++ is used to store the memory address of its pointee (memory address of an object — an instance of a class).

Book* myPointer = new Book(); // myPointer could be an instance of the Book class or any subclass of the
// Book class

Every time we allocate memory on the heap (through the use of pointers), we must remember to deallocate/reallocate the memory on the heap in order to make the memory available again for use by other parts of the program. This can be done by using the delete keyword like this:

delete myPointer; // or delete[] myPointers where myPointers be an array

Failure to delete a pointer or pointers can result in memory leak (where the memory allocated from the free store wouldn’t be available for use by other parts of the program). So a programmer must always keep track of his pointers and try to curb the risk of letting pointers go out of scope without deallocating the memory used by corresponding pointees. It is hard, especially in a complicated/verbose source, for the programmer to keep track of all pointers used and try to delete them. Smart pointers simplify this task.

There are different ways to implement smart pointers. Some of which are through the use of reference counting and/or operator overloading. However, in C++, smart pointers may be implemented as a template class that mimics, by means of operator overloading, the behavior of traditional (raw) pointers, (e.g.: dereferencing, assignment) while providing additional memory management algorithms. An example pointer implementation is the BOOST library, a high-quality open-source library, that has been considered for inclusion into the standard C++ library. This library provides the following pointer implementations:

shared_ptr<T> pointer to T" using a reference count to determine when the object is no longer needed. shared_ptr is the generic, most versatile smart pointer offered by boost.
scoped_ptr<T> a pointer automatically deleted when it goes out of scope. No assignment possible, but no performance penalties compared to “raw” pointers
intrusive_ptr<T> another reference counting pointer. It provides better performance than shared_ptr, but requires the type T to provide its own reference counting mechanism.
weak_ptr<T> a weak pointer, working in conjunction with shared_ptr to avoid circular references
shared_array<T> like shared_ptr, but access syntax is for an Array of T
scoped_array<T> like scoped_ptr, but access syntax is for an Array of T

I can’t go through all these implementations in this article. For more details, check out the online docs. of the C++ BOOST library. In addition, the C++ standard library provides a class template called auto_ptr (declared in the memory header file) that provides some basic supplementary memory management capabilities for C++ raw pointers.

Smart pointers do not only help in memory management but also help support intentional programming (when the programmer code reflects his intention — his original conception when he was about to start coding). For example, if the programmer wanted to make a pointer function (which is, by the way, useful for making functions polymorphic) like this: Book* myPointerFunction();. If he were to use raw pointers, he would have to figure out how he would delete myPointerFunction(). On the other hand, if he had access to smart pointers he wouldn’t have to worry about deleting myPointerFunction(); , thus more readily portraying the programmer’s intention without side effects.

In programming languages like Java, C#, VB, and Python, the deleting of “pointers” (there are no explicit pointers) are done through their respective garbage collection algorithms and mechanisms. So programmers wouldn’t have to worry unnecessarily about deleting pointers. Even these programming language have different garbage collection schemes depending on the implementation. The standard C implementation (CPython) uses reference counting to  detect inaccessible objects, and a separate mechanism to collect reference cycles, periodically executing a cycle detection algorithm which looks for inaccessible cycles and deletes the objects involved. The gc module provides functions to force garbage collection, obtain debugging statistics, and tune the collector’s parameters. On the other hand, Jython relies on the Java runtime so the JVM’s garbage collector is used. The same applies to IronPython, which uses the CLR garbage collector. This difference can cause some subtle porting problems if your Python code depends on the behavior of the reference counting implementation.

A major demerit in using smart pointers is that the encapsulating nature of smart pointers could cause problems when pointers are used with a “rigid” frameworks that only accept raw pointers. This can be very difficult to handle unless the smart pointer implementation, in this case, has an implicit conversion scheme to its raw pointer type (a dangerous thing indeed).

I must say that the disadvantages of using pointers is trivial! On the other hand, they could ultimately save the programmer’s code-writing and debugging time and improve the quality of the software in which they are used. Overall, smart pointers are very useful if they are needed (that is, when there is a somewhat heavy/tangled/non-explicit use of pointers) but must be used wisely and carefully.

Frustrating FAT32

Since Monday morning, I have been trying to copy some files (about 2TB) to a RAID I set up in my office. My supervisor instructed me to diff. (compare these files) with some other files on another drive (stored on the network) and ascertain the differences. I initially thought that copying the files from the 2 1TB drive was going to be very easy. But I was gravely mistaking!

FAT32….. Why does FAT32 still exist? Do people ever use this again? Who made this format in the first place? End of Rant.

As I already said, I started working on transferring these files to the RAID since Monday. I had no much problem with transferring files from the first hard drive. That was really encouraging. My morale for work was boosted. As I began transferring the files from the second drive, the whole system “sort of” crashed. Even, the Mac program “Finder” crashed. It issued an error: “The application Finder cannot be opened”. And it displayed a cryptic error code, something like “1009-“. I have no idea what that means! I opened the terminal so that I can kill Finder and restart it. Surprisingly, even the terminal said it was busy running another process. So I left it alone. The whole system was down. I was perplexed and worried. I wandered why this could be happening and tried to look for a solution online (luckily, firefox didn’t crash). I found none relating to this problem.

Having tried to resurrect my programs again without any success, I decided to restart the whole system quitting all the programs using CTRL-OPTION-ESC. This worked! The system restarted but I couldn’t read any files from the second 1TB drive. I was on the hot sit!

I tried repairing, ejecting safely, and even ‘resurrecting’ (some complex repair processes I made up) but none worked for me. The OS didn’t just recognize the disk. Then out of serendipity I checked the disk information to discover that the drive was a FAT32. I suppose that that might have been the problem all along. I discussed this issue with a technical personnel in the ITS ‘basement’ and he confirmed my suspicions. He said that Macs aren’t on good terms with old FAT32 and that could have accounted for the weird behavior of my drives.

Don’t get me wrong. FAT32’s aren’t that bad. They are good to windows but kind of BAD to Macs. FAT32’s have some enviable characters. FAT32’s allow you have a root folder that is an ordinary cluster chain. Plus, you don’t have any superfluous files that *nix files sometimes put in the root folder of a drive anytime it writes to that drive. In addition, this format is safer than many others because the boot sector of FAT32 drives is automatically backed up at a specified location on the volume so FAT32 volumes are less susceptible to single points of failure than a lot of *nix formats including its predecessor FAT16 (pls. don’t use this).

On the other hand, FAT32 has a lot of demerits. The file format does not have any built-in file system security or compression scheme with FAT32. Also, it is more susceptible to viruses (this is something associated with all Windows platforms). I don’t have proof for this but I’ve noticed that viruses are more prevalent in FAT32 volumes than on any other non-FAT volumes.

Now, I should get back to trying to copy files from my *Wonderful* FAT32 drive to the Mac RAID that I set up. Peace.