Garbage collection As a collection algorithm, reference counting tracks, for each object, a count of the number of
references to it held by other objects. If an object's reference count reaches zero, the object has become inaccessible, and can be destroyed. When an object is destroyed, any objects referenced by that object also have their reference counts decreased. Because of this, removing a single reference can potentially lead to a large number of objects being freed. A common modification allows reference counting to be made incremental: instead of destroying an object as soon as its reference count becomes zero, it is added to a list of unreferenced objects, and periodically (or as needed) one or more items from this list are destroyed. Simple reference counts require frequent updates. Whenever a reference is destroyed or overwritten, the reference count of the object it references is decremented, and whenever one is created or copied, the reference count of the object it references is incremented. Reference counting is also used in file systems and distributed systems, where full non-incremental tracing garbage collection is too time-consuming because of the size of the object graph and slow access speed.
Component Object Model Microsoft's
Component Object Model (COM) and
WinRT makes pervasive use of reference counting. In fact, two of the three methods that all COM objects must provide (in the
IUnknown interface) increment or decrement the reference count. Much of the
Windows Shell and many Windows applications (including
MS Internet Explorer,
MS Office, and countless third-party products) are built on COM, demonstrating the viability of reference counting in large-scale systems. One primary motivation for reference counting in COM is to enable interoperability across different programming languages and runtime systems. A client need only know how to invoke object methods in order to manage object life cycle; thus, the client is completely abstracted from whatever memory allocator the implementation of the COM object uses. As a typical example, a
Visual Basic program using a COM object is agnostic towards whether that object was allocated (and must later be deallocated) by a C++ allocator or another Visual Basic component.
C++ C++ does not perform reference-counting by default, fulfilling its philosophy of not adding functionality that might incur overheads where the user has not explicitly requested it. Objects that are shared but not owned can be accessed via a reference, raw pointer, or
iterator (a conceptual generalisation of pointers). However, by the same token, C++ provides native ways for users to opt-into such functionality:
C++11 provides reference counted
smart pointers, via the Shared ptr| class, enabling automatic shared memory-management of dynamically allocated objects. Programmers can use this in conjunction with
weak pointers (via Shared ptr|) to break cyclic dependencies. Objects that are dynamically allocated but not intended to be shared can have their lifetime automatically managed using a Shared ptr|. In addition,
C++11's move semantics further reduce the extent to which reference counts need to be modified by removing the deep copy normally used when a function returns an object, as it allows for a simple copy of the pointer of said object.
Cocoa (Objective-C) Apple's
Cocoa and
Cocoa Touch frameworks (and related frameworks, such as
Core Foundation) use manual reference counting, much like
COM. Traditionally this was accomplished by the programmer manually sending retain and release messages to objects, but
Automatic Reference Counting, a
Clang compiler feature that automatically inserts these messages as needed, was added in
iOS 5 and
Mac OS X 10.7.
Mac OS X 10.5 introduced a tracing garbage collector as an alternative to reference counting, but it was deprecated in
OS X 10.8 and removed from the Objective-C
runtime library in
macOS Sierra.
iOS has never supported a tracing garbage collector.
Delphi Delphi is mostly not a garbage collected language, in that user-defined types must still be manually allocated and deallocated; however, it does provide automatic collection using reference counting for a few built-in types, such as strings,
dynamic arrays, and interfaces, for ease of use and to simplify the generic database functionality. It is up to the programmer to decide whether to use the built-in types; Delphi programmers have complete access to low-level memory management like in C/C++. So all potential cost of Delphi's reference counting can, if desired, be easily circumvented. Some of the reasons reference counting may have been preferred to other forms of garbage collection in Delphi include: • The general benefits of reference counting, such as prompt collection. • Cycles either cannot occur or do not occur in practice because none of the garbage-collected built-in types are recursive. (using interfaces one could create such scenario, but that is not common usage) • The overhead in code size required for reference counting is very small (on native x86, typically a single LOCK INC, LOCK DEC or LOCK XADD instruction, which ensures atomicity in any environment), and no separate thread of control is needed for collection as would be needed for a tracing garbage collector. • Many instances of the most commonly used garbage-collected type, the string, have a short lifetime, since they are typically intermediate values in string manipulation. A lot of local string usage could be optimized away, but the compiler currently doesn't do it. • The reference count of a string is checked before mutating a string. This allows reference count 1 strings to be mutated directly whilst higher reference count strings are copied before mutation. This allows the general behaviour of old style
Pascal strings to be preserved whilst eliminating the cost of copying the string on every assignment. • Because garbage-collection is only done on built-in types, reference counting can be efficiently integrated into the library routines used to manipulate each datatype, keeping the overhead needed for updating of reference counts low. Moreover, a lot of the runtime library is in hand-optimized assembler. • The string type can be cast to a pointer to char, and high performance operations can be performed that way. This is important since both Delphi and FPC implement their RTL in Pascal. Various other automated types have such casting options.
GObject The
GObject object-oriented programming framework implements reference counting on its base types, including
weak references. Reference incrementing and decrementing uses
atomic operations for thread safety. A significant amount of the work in writing bindings to GObject from high-level languages lies in adapting GObject reference counting to work with the language's own memory management system. The
Vala programming language uses GObject reference counting as its primary garbage collection system, along with copy-heavy string handling.
Perl Perl also uses reference counting, without any special handling of circular references, although (as in Cocoa and C++ above), Perl does support weak references, which allows programmers to avoid creating a cycle.
PHP PHP uses a reference counting mechanism for its internal variable management. Since PHP 5.3, it implements the algorithm from Bacon's above mentioned paper. PHP allows you to turn on and off the cycle collection with user-level functions. It also allows you to manually force the purging mechanism to be run. $a = "new string"; $b = $a; xdebug_debug_zval("a"); The above example will output: a: (refcount=2, is_ref=0)='new string'
Python Python also uses reference counting and offers cycle detection as well (and can reclaim reference cycles).
Rust Like other low-level languages,
Rust does not provide reference counting by default. Instead, any constructed type will be
dropped when it falls out of scope. When a programmer needs to define the scope of a constructed type, they often use lifetimes. However, the language also offers various alternatives to complex forms of memory management. Reference counting functionality is provided by the Rc and Arc types, which are non-atomic and atomic respectively. For example, the type Rc provides shared ownership of a value of type T, allocated on the heap for multiple references to its data. use std::rc::Rc; struct Cat { color: String, } fn main() { let cat = Cat { color: "black".to_string() }; let cat = Rc::new(cat); } Using these constructs allows programmers to avoid lifetimes for a small runtime cost. Both reference counters keep track of the number of owners, as they must drop themselves when no owners remain. One noteworthy facet of these types is related to their usage as a shared reference. In Rust, shared references cannot mutate their held data, so Rc often comes bundled with Cell, and Arc with Mutex, in contexts where interior mutability is necessary. Interior mutability without UnsafeCell has performance costs, too, so, for maximum performance, some applications may call for additional complexity.
Squirrel Squirrel uses reference counting with cycle detection. This tiny language is relatively unknown outside the video game industry; however, it is a concrete example of how reference counting can be practical and efficient (especially in realtime environments).
Swift Swift uses reference counting to track and manage the memory of class instances, and provides the weak keyword for creating weak references. Instances of
value types do not use reference counting.
Tcl Tcl 8 uses reference counting for memory management of values (Tcl Obj
structs). Since Tcl's values are immutable, reference cycles are impossible to form and no cycle detection scheme is needed. Operations that would replace a value with a modified copy are generally optimized to instead modify the original when its reference count indicates that it is not shared. The references are counted at a data structure level, so the problems with very frequent updates discussed above do not arise.
Xojo Xojo also uses reference counting, without any special handling of circular references, although (as in Cocoa and C++ above), Xojo does support weak references, which allows programmers to avoid creating a cycle.
File systems Many file systems maintain reference counts to any particular block or file, for example the
inode link count on
Unix-style file systems, which are usually known as
hard links. When the count reaches zero, the file can be safely deallocated. While references can still be made from
directories, some Unixes only allow references from live processes, and there can be files that exist outside the file system hierarchy. == References ==