Civil Rights
Movements, leaders, victories and the continuing fight for equality.
Explore the people, places, events, achievements, struggles and stories that shaped our journey.
Movements, leaders, victories and the continuing fight for equality.
Innovation, patents, science, technology and world-changing contributions.
Pioneers, champions, Negro Leagues, records, activism and excellence.
Meet the people whose lives, choices and achievements shaped the journey.
Black towns, communities, institutions and places where history happened.
Moments that changed communities, movements, institutions and the nation.
Katherine Johnson’s mathematical calculations helped guide some of America’s most important early space missions while she confronted the racial and gender barriers faced by Black women in twentieth-century America.
MORE →Reflects the personal views, recollections, and perspective of the author, Mike Davis.
This is a personal recollection on the Move fire on May 13, 1985

Dangling pointers and wild pointers in computer programming are pointers that do not point to a valid object of the appropriate type. These are special cases of memory safety violations. More generally, dangling references and wild references are references that do not resolve to a valid destination.
Dangling pointers arise during object destruction, when an object that is pointed to by a given pointer is deleted or deallocated, without modifying the value of that said pointer, so that the pointer still points to the memory location of the deallocated memory. The system may reallocate the previously freed memory, and if the program then dereferences the (now) dangling pointer, unpredictable behavior may result, as the memory may now contain completely different data. If the program writes to memory referenced by a dangling pointer, a silent corruption of unrelated data may result, leading to subtle bugs that can be extremely difficult to find. If the memory has been reallocated to another process, then attempting to dereference the dangling pointer can cause segmentation faults (UNIX, Linux) or general protection faults (Windows). If the program has sufficient privileges to allow it to overwrite the bookkeeping data used by the kernel's memory allocator, the corruption can cause system instabilities. In object-oriented languages with garbage collection, dangling references are prevented by only destroying objects that are unreachable, meaning they do not have any incoming pointers; this is ensured either by tracing or reference counting. However, a finalizer may create new references to an object, requiring object resurrection to prevent a dangling reference.
Wild pointers, also called uninitialized pointers, arise when a pointer is used prior to initialization to some known state, which is possible in some programming languages. They show the same erratic behavior as dangling pointers, though they are less likely to stay undetected because many compilers will raise a warning at compile time if declared variables are accessed before being initialized.[1]
In many languages (e.g., the C programming language) deleting an object from memory explicitly or by destroying the stack frame on return does not alter associated pointers. The pointer still points to the same location in memory even though that location may now be used for other purposes.
A straightforward example is shown below:
{
char* dp = NULL;
// ...
{
char c;
dp = &c;
}
// c falls out of scope
// dp is now a dangling pointer
}
If the operating system is able to detect run-time references to null pointers, a solution to the above is to assign 0 (null) to dp immediately before the inner block is exited. Another solution would be to somehow guarantee dp is not used again without further initialization.
Another frequent source of dangling pointers is a jumbled combination of malloc() and free() library calls: a pointer becomes dangling when the block of memory it points to is freed. As with the previous example one way to avoid this is to make sure to reset the pointer to null after freeing its reference—as demonstrated below.
#include <stdlib.h>
void func() {
char* dp = (char*)malloc(sizeof(char) * 10);
// ...
free(dp); // dp now becomes a dangling pointer
dp = NULL; // dp is no longer dangling
// ...
}
An all too common misstep is returning addresses of a stack-allocated local variable: once a called function returns, the space for these variables gets deallocated and technically they have "garbage values".
int* func(void) {
int num = 1234;
// ...
return #
}
Attempts to read from the pointer may still return the correct value (1234) for a while after calling func, but any functions called thereafter may overwrite the stack storage allocated for num with other values and the pointer would no longer work correctly. If a pointer to num must be returned, num must have scope beyond the function—it might be declared as static.
Antoni Kreczmar (1945–1996) has created a complete object management system which is free of dangling reference phenomenon.[2] A similar approach was proposed by Fisher and LeBlanc[3] under the name Locks-and-keys.
Wild pointers are created by omitting necessary initialization prior to first use. Thus, strictly speaking, every pointer in programming languages which do not enforce initialization begins as a wild pointer.
This most often occurs due to jumping over the initialization, not by omitting it. Most compilers are able to warn about this.
int f(int i) {
char* dp; // dp is a wild pointer
static char* scp; /* scp is not a wild pointer:
* static variables are initialized to 0
* at start and retain their values from
* the last call afterwards.
* Using this feature may be considered bad
* style if not commented */
}
Like buffer-overflow bugs, dangling/wild pointer bugs frequently become security holes. For example, if the pointer is used to make a virtual function call, a different address (possibly pointing at exploit code) may be called due to the vtable pointer being overwritten. Alternatively, if the pointer is used for writing to memory, some other data structure may be corrupted. Even if the memory is only read once the pointer becomes dangling, it can lead to information leaks (if interesting data is put in the next structure allocated there) or to privilege escalation (if the now-invalid memory is used in security checks). When a dangling pointer is used after it has been freed without allocating a new chunk of memory to it, this becomes known as a "use after free" vulnerability.[4] For example, CVE-2014-1776 is a use-after-free vulnerability in Microsoft Internet Explorer 6 through 11[5] that was used by zero-day attacks by an advanced persistent threat.[6]
In C, the simplest technique is to implement an alternative version of the free() (or alike) function which guarantees the reset of the pointer. However, this technique will not clear other pointer variables which may contain a copy of the pointer.
#include <assert.h>
#include <stdlib.h>
// Safe version of free()
static void safeFree(void** pp) {
// in debug mode, abort if pp is NULL
assert(pp);
// free(NULL) works properly, so no check is required besides the assert in debug mode
free(*pp); // deallocate chunk, note that free(NULL) is valid
*pp = NULL; // reset original pointer
}
int f(int i) {
char* p = NULL;
char* p2;
p = (char*)malloc(1000); // get a chunk
p2 = p; // copy the pointer
// use the chunk here
safeFree((void**)&p); // safety freeing; does not affect p2 variable
safeFree((void**)&p); // this second call won't fail as p is reset to NULL
char c = *p2; // p2 is still a dangling pointer, so this is undefined behavior.
return i + c;
}
The alternative version can be used even to guarantee the validity of an empty pointer before calling malloc():
safeFree(&p); // I'm not sure if chunk has been released */
p = (char*)malloc(1000); // allocate now
These uses can be masked through #define directives to construct useful macros (a common one being #define XFREE(ptr) safeFree((void**)&(ptr))), creating something like a metalanguage or can be embedded into a tool library apart. In every case, programmers using this technique should use the safe versions in every instance where free() would be used; failing in doing so leads again to the problem. Also, this solution is limited to the scope of a single program or project, and should be properly documented.
Among more structured solutions, a popular technique to avoid dangling pointers in C++ is to use smart pointers. A smart pointer typically uses reference counting to reclaim objects. Some other techniques include the tombstones method and the locks-and-keys method.[3]
Another approach is to use the Boehm garbage collector, a conservative garbage collector that replaces standard memory allocation functions in C and C++ with a garbage collector. This approach completely eliminates dangling pointer errors by disabling frees, and reclaiming objects by garbage collection.
Another approach is to use a system such as CHERI, which stores pointers with additional metadata which may prevent invalid accesses by including lifetime information in pointers. CHERI typically requires support in the CPU to conduct these additional checks.
In languages like Java, dangling pointers cannot occur because there is no mechanism to explicitly deallocate memory. Rather, the garbage collector may deallocate memory, but only when the object is no longer reachable from any references.
In the language Rust, the type system has been extended to include also the variables lifetimes and resource acquisition is initialization. Unless one disables the features of the language, dangling pointers will be caught at compile time and reported as programming errors.
To expose dangling pointer errors, one common programming technique is to set pointers to the null pointer or to an invalid address once the storage they point to has been released. When the null pointer is dereferenced (in most languages) the program will immediately terminate—there is no potential for data corruption or unpredictable behavior. This makes the underlying programming mistake easier to find and resolve. This technique does not help when there are multiple copies of the pointer.
Some debuggers will automatically overwrite and destroy data that has been freed, usually with a specific pattern, such as 0xDEADBEEF (Microsoft's Visual C/C++ debugger, for example, uses 0xCC, 0xCD or 0xDD depending on what has been freed[7]). This usually prevents the data from being reused by making it useless and also very prominent (the pattern serves to show the programmer that the memory has already been freed).
Tools such as Polyspace, TotalView, Valgrind, Mudflap,[8] AddressSanitizer, or tools based on LLVM[9] can also be used to detect uses of dangling pointers.
Other tools (SoftBound, Insure++, and CheckPointer) instrument the source code to collect and track legitimate values for pointers ("metadata") and check each pointer access against the metadata for validity.
Another strategy, when suspecting a small set of classes, is to temporarily make all their member functions virtual: after the class instance has been destructed/freed, its pointer to the Virtual Method Table is set to NULL, and any call to a member function will crash the program and it will show the guilty code in the debugger.
The ARM64 memory tagging extension (MTE) - disabled by default on Linux systems, but can be enabled on Android 16 - triggers a segmentation fault when it detects use-after-free and buffer overflow.[10][11]
Source: Wikipedia. Article content is retrieved live through the MediaWiki API.
Dangling pointers and wild pointers in computer programming are pointers that do not point to a valid object of the appropriate type. These are special cases of memory safety violations. More generally, dangling references and wild references are references that do not resolve to a valid destination. Dangling pointers arise during object destruction, when an object that is pointed to by a given pointer is deleted or deallocated, without modifying the value of that said pointer, so that the pointer still points to the memory location of the deallocated memory. The system may reallocate the previously freed memory, and if the program then dereferences the (now) dangling pointer, unpredictable behavior may result, as the memory may now contain completely different data. If the program writes to memory referenced by a dangling pointer, a silent corruption of unrelated data may result, leading to subtle bugs that can be extremely difficult to find. If the memory has been reallocated to another process, then attempting to dereference the dangling pointer can cause segmentation faults (UNIX, Linux) or general protection faults (Windows). If the program has sufficient privileges to allow it to overwrite the bookkeeping data used by the kernel's memory allocator, the corruption can cause system instabilities. In object-oriented languages with garbage collection, dangling references are prevented by only destroying objects that are unreachable, meaning they do not have any incoming pointers; this is ensured either by tracing or reference counting. However, a finalizer may create new references to an object, requiring object resurrection to prevent a dangling reference. Wild pointers, also called uninitialized pointers, arise when a pointer is used prior to initialization to some known state, which is possible in some programming languages. They show the same erratic behavior as dangling pointers, though they are less likely to stay undetected because many compilers will raise a warning at compile time if declared variables are accessed before being initialized.
In computer science, a smart pointer is an abstract data type that simulates a pointer while providing added features, such as automatic memory management or bounds checking. Such features are intended to reduce bugs caused by the misuse of pointers, while retaining efficiency. Smart pointers typically keep track of the memory they point to, and may also be used to manage other resources, such as network connections and file handles. Smart pointers were first popularized in the programming language C++ during the first half of the 1990s as rebuttal to criticisms of C++'s lack of automatic garbage collection. Rust, which avoids raw pointers and uses ownership to dictate lifetimes, also has smart pointers. Pointer misuse can be a major source of bugs. Smart pointers prevent most situations of memory leaks by making the memory deallocation automatic. More generally, they make object destruction automatic: an object controlled by a smart pointer is automatically destroyed (finalized and then deallocated) when the last (or only) owner of an object is destroyed, for example because the owner is a local variable, and execution leaves the variable's scope. Smart pointers also eliminate dangling pointers by postponing destruction until an object is no longer in use. If a language supports automatic garbage collection (for example, Java or C#), then smart pointers are unneeded for reclaiming and safety aspects of memory management, yet are useful for other purposes, such as cache data structure residence management and resource management of objects such as file handles or network sockets. Java, although not having a pointer API, has similar concepts for dealing with references. Several types of smart pointers exist. Some work with reference counting, others by assigning ownership of an object to one pointer.
Memory corruption occurs in a computer program when the contents of a memory location are modified due to programmatic behavior that exceeds the intention of the original programmer or program/language constructs; this is termed as violation of memory safety. The most likely causes of memory corruption are programming errors (software bugs). When the corrupted memory contents are used later in that program, it leads either to program crash or to strange and bizarre program behavior. Nearly 10% of application crashes on Windows systems are due to heap corruption. Modern programming languages like C and C++ have powerful features of explicit memory management and pointer arithmetic. These features are designed for developing efficient applications and system software. However, using these features incorrectly may lead to memory corruption errors. Memory corruption is one of the most intractable class of programming errors, for two reasons: The source of the memory corruption and its manifestation may be far apart, making it hard to correlate the cause and the effect. Symptoms appear under unusual conditions, making it hard to consistently reproduce the error. Memory corruption errors can be broadly classified into four categories: Using uninitialized memory: Contents of uninitialized memory are treated as garbage values. Using such values can lead to unpredictable program behavior. Using non-owned memory: It is common to use pointers to access and modify memory. If such a pointer is a null pointer, dangling pointer (pointing to memory that has already been freed), or to a memory location outside of current stack or heap bounds, it is referring to memory that is not then possessed by the program. Using such pointers is a serious programming flaw. Accessing such memory usually causes operating system exceptions, that most commonly lead to a program crash (unless suitable memory protection software is being used). Using memory beyond the memory that was allocated (buffer overflow): If an array is used in a loop, with incorrect terminating condition, memory beyond the array bounds may be accidentally manipulated. Buffer overflow is one of the most common programming flaws exploited by computer viruses, causing serious computer security issues (e.g. return-to-libc attack, stack-smashing protection) in widely used programs. In some cases programs can also incorrectly access the memory before the start of a buffer. Faulty heap memory management: Memory leaks and freeing non-heap or un-allocated memory are the most frequent errors caused by faulty heap memory management. Many memory debuggers such as Purify, Valgrind, Insure++, Parasoft C/C++test, AddressSanitizer are available to detect memory corruption errors.
Tombstones are a mechanism to detect dangling pointers and mitigate the problems they can cause in computer programs. Dangling pointers can appear in certain computer programming languages, e.g. C, C++ and assembly languages. A tombstone is a structure that acts as an intermediary between a pointer and its target, often heap-dynamic data in memory. The pointer – sometimes called the handle – points only at tombstones and never to its actual target. When the data is deallocated, the tombstone is set to a null (or, more generally, to a value that is illegal for a pointer in the given runtime environment), indicating that the variable no longer exists. This mechanism prevents the use of invalid pointers, which would otherwise access the memory area that once belonged to the now deallocated variable, although it may already contain other data, in turn leading to corruption of in-memory data. Depending on the operating system, the CPU can automatically detect such an invalid access (e.g. for the null value: a null pointer dereference error). This supports in analyzing the actual reason, a programming error, in debugging, and it can also be used to abort the program in production use, to prevent it from continuing with invalid data structures. In more generalized terms, a tombstone can be understood as a marker for "this data is no longer here". For example, in filesystems it may be efficient when deleting files to mark them as "dead" instead of immediately reclaiming all their data blocks. The downsides of using tombstones include a computational overhead and additional memory consumption: extra processing is necessary to follow the path from the pointer to data through the tombstone, and extra memory is necessary to retain tombstones for every pointer throughout the program. One other problem is that all the code that needs to work with the pointers in question needs to be implemented to use the tombstone mechanism. Among popular programming languages, C++ implements the tombstone pattern in its standard library as a weak pointer using std::weak_ptr. Built–in support by programming languages or the compiler is not necessary to use this mechanism.
Before the 1921 destruction of Tulsa’s Greenwood District, Black residents had created a remarkable center of business and community life. The district included stores, professional offices, entertainment venues and homes owned by Black citizens. Understanding Greenwood means learning what was built—not only what was burned.
MORE →Madam C.J. Walker