Dangling Pointer in C: Causes, Types, Fixes & Examples
A dangling pointer in C is a pointer that still stores the address of an object whose lifetime has ended. It matters because dereferencing such an address can corrupt data, crash a program, or expose security bugs such as use-after-free in payment, booking, or authentication systems.
Dangling pointers sit at the intersection of memory lifetime, ownership, and pointer aliasing. If you already know pointer basics, the next step is recognising when an address becomes invalid; for a related foundation, see Function Pointers in C when reviewing pointer syntax and indirection.
After reading, you will be able to identify every common dangling pointer pattern, explain what is a dangling pointer in interviews, fix real C code safely, and avoid undefined behaviour in heap, stack, scope, aliasing, and reallocation scenarios.
Who This Guide Is For
This guide is specifically designed for:
Core Concepts
Dangling pointers occur when a pointer value outlives the object it points to. The C language does not automatically track whether an address is still valid, so the programmer must manage lifetime boundaries: allocation, deallocation, scope exit, function return, and reallocation. The common variants are heap use-after-free, returning the address of an automatic local variable, storing a block-scope address beyond its scope, stale aliases after free, stale pointers after realloc, and owner-lifetime mismatches inside structs or containers. For comparison with a language that provides different pointer tools and ownership conventions, see C++ Pointers.
1.Heap After Free
The most recognised dangling pointer in C is a heap pointer used after free(). Memory obtained through malloc, calloc, or realloc remains valid only until it is deallocated. Once free(ptr) is called, the pointer variable still contains the old numeric address, but the object no longer exists. Dereferencing it is undefined behaviour: the program may appear to work, print stale data, crash, or overwrite memory that the allocator has already reused.
A familiar Indian-context example is a UPI transaction object allocated while processing a payment. If the transaction record is freed after sending a response, but a later logging function still reads txn->amount, the pointer is dangling. An industry-specific example is a healthcare device gateway that frees a patient-reading buffer after upload, while a retry queue still holds the old address. In both cases, the dangerous part is not the address itself but the false assumption that the object still has a valid lifetime.
Code Example
2.Returning Local Address
A pointer becomes dangling when a function returns the address of an automatic local variable. Local variables declared inside a function usually have automatic storage duration: they are created when execution enters their block and destroyed when execution leaves it. Returning &local gives the caller an address to an object that no longer exists. Some compilers warn about this pattern, but a warning is not the rule; the rule is that using the returned pointer is invalid.
A familiar example is a PAN verification helper that builds a temporary status code inside a function and returns its address to the caller. The caller may see the expected value during testing, then fail unpredictably after another function call overwrites the same stack area. An industry-specific SaaS example is a tenant-configuration loader returning the address of a local struct Config. The API looks efficient, but it hands back a dead object. Safe alternatives are returning by value, using caller-provided storage, or allocating dynamically with a clear responsibility to free.
Code Example
3.Escaped Block Address
A dangling pointer can also be created without calling free(). In C, a variable declared inside a nested block, such as an if, for, or standalone { } block, stops existing when execution leaves that block. If a pointer declared outside the block stores the address of that inner variable, the pointer becomes dangling immediately after the block ends.
A familiar example is an IRCTC booking flow that stores the address of a temporary seat number declared inside an if (confirmed) block, then prints it after the block. It may look harmless because the function has not returned yet, but the seat variableβs scope has already ended. An industry-specific banking example is storing the address of a temporary fraud-score variable created inside a rule branch, then passing it to an audit function outside the branch. The mental model is simple: scope is a lifetime boundary. If the variable is born inside a smaller block, pointers to it must not escape that block.
Code Example
4.Stale Alias Pointer
Dangling pointers often survive through aliases. An alias is another pointer holding the same address as the owner pointer. If one pointer calls free(), every alias to that allocation becomes invalid, not just the pointer passed to free(). Setting only the owner pointer to NULL does not magically clear other copies of the same address. This is why ownership discipline matters more than just sprinkling ptr = NULL everywhere.
A familiar example is a Zomato order tracker where current_order and display_order point to the same heap object. If checkout frees current_order while the UI still reads display_order, the UI alias is dangling. An industry-specific e-commerce example is a product-cache entry referenced by both a recommendation engine and a pricing updater. If the cache eviction path frees the product object while the pricing updater keeps an alias, later reads can corrupt prices or crash the process. This issue is frequently discussed in systems interviews because it tests whether the candidate understands that pointer values can be copied, but object lifetime is shared.
Code Example
5.After Realloc
realloc is a frequent source of dangling pointers because it can resize an allocation in place or move it to a new location. If it moves the allocation, the old pointer value becomes invalid. If other aliases still point to the old address, they become dangling. Another important detail: assigning realloc directly to the original pointer can lose the original allocation if realloc fails and returns NULL. The safer pattern is to store the result in a temporary pointer, check it, and then update the owner.
A familiar example is resizing an Aadhaar-masking buffer from a short preview to a full formatted string. If the buffer moves and an old pointer is still used for printing, the program may read freed memory. An industry-specific ed-tech example is expanding a dynamic array of quiz attempts for a live test platform. If an analytics module keeps a pointer to the old array while the submission service calls realloc, the analytics pointer can become stale. The fix is not to avoid realloc, but to treat it as a lifetime-changing operation.
Code Example
6.Owner Lifetime Mismatch
A more advanced dangling pointer bug appears when structs, containers, callback records, or background jobs store pointers to data owned elsewhere. The pointer may be valid when stored, but becomes dangling later because the owner object dies first. These bugs are harder to spot because the invalid dereference may happen far away from the line that created the pointer.
A familiar example is a mobile recharge receipt struct storing a pointer to a temporary operator name buffer owned by a parsing function. The receipt is saved for later printing, but the parserβs buffer disappears. An industry-specific example is a network server that stores request->user_agent inside an async logging job, then frees the request immediately after responding. When the logger runs, it reads a pointer into a destroyed request buffer. The robust choices are deep-copy the data into the long-lived object, require the owner to outlive all borrowers, or use an API contract that clearly distinguishes owning and non-owning pointers. This type also matters when callbacks and function pointers are stored with context pointers; the function pointer may be valid, but its context pointer can dangle. For callback syntax review, Function Pointers in C is directly relevant.
Code Example
Learning Path
Mastering dangling pointers requires more than memorising a definition. Practise object lifetime, ownership, and debugging together so that you can reason about real C programs instead of only identifying textbook snippets.
Frequently Asked Questions
What is Dangling Pointer in C?
A dangling pointer in C is a pointer that refers to memory whose object lifetime has ended. The pointer may still contain an address, but dereferencing it causes undefined behaviour and can lead to crashes, data corruption, or security vulnerabilities.
What is a dangling pointer with example?
A simple dangling pointer in C example is allocating an integer using malloc, freeing it using free(ptr), and then reading *ptr. After free, the heap object no longer exists, so ptr is a stale address even if it is not automatically changed to NULL.
How is a dangling pointer different from a NULL pointer?
A NULL pointer intentionally points to no object and can be checked before use. A dangling pointer looks like an ordinary non-NULL address but refers to an object that has already died, making it more dangerous because simple non-NULL checks do not prove validity.
How is a dangling pointer different from a wild pointer?
A wild pointer is uninitialised and contains an indeterminate address from the start. A dangling pointer was once valid, but became invalid after the pointed objectβs lifetime ended through free, scope exit, function return, or reallocation.
Can setting a pointer to NULL prevent dangling pointers?
Setting a pointer to NULL after free prevents that specific pointer variable from being accidentally dereferenced. It does not fix other aliases that already copied the same address, so ownership design and alias control are still required.
Why is returning address of local variable wrong in C?
A local automatic variable is destroyed when the function returns. Returning its address gives the caller a pointer to an object that no longer exists, so using that pointer is undefined behaviour.
Does realloc always create a dangling pointer?
No. realloc may resize the block in place, in which case the address may remain the same. But code must be written as if the allocation can move, because old aliases become dangling if realloc returns a different address.
How do you detect dangling pointers in C?
Use compiler warnings, code review focused on ownership, and runtime tools such as AddressSanitizer or Valgrind on supported platforms. AddressSanitizer is especially useful for catching heap-use-after-free during testing.
Interview Preparation
Dangling pointers appear in interviews because they test C fundamentals, memory management discipline, undefined behaviour, and debugging maturity. A strong answer should identify the lifetime boundary first, then explain why dereferencing is invalid, and finally propose a safe fix.
Conceptual Questions
- What is dangling pointer? A dangling pointer is a pointer that still holds the address of an object whose lifetime has ended. The key phrase interviewers expect is βundefined behaviour on dereference.β
- Why does free() not automatically make a pointer NULL? In C,
freereceives a copy of the pointer value, not the pointer variable itself. It releases the allocation but cannot rewrite every pointer variable or alias that stores the same address. - Is checking ptr != NULL enough to prove a pointer is valid? No. A dangling pointer can be non-NULL and still invalid because it points to dead storage. NULL checks prevent null dereference, not use-after-free.
- What is undefined behaviour in the context of dangling pointers? Undefined behaviour means the C standard imposes no required result. The program may print expected data, crash immediately, corrupt unrelated memory, or behave differently under optimisation.
Applied / Problem-Solving Questions
- How would you fix a function that returns the address of a local array? Prefer caller-provided output storage or return a struct by value when practical. Dynamic allocation is also possible, but the API must clearly state who frees the memory.
- How do you safely resize a dynamic array using realloc? Assign
reallocto a temporary pointer, check forNULL, and update the owner only after success. Then ensure no stale aliases continue using the old address. - How would you debug a suspected use-after-free crash? Rebuild with warnings and sanitizers, reproduce with a small input, and inspect the allocation and free paths. Track all aliases to the freed object and identify which one is used after lifetime ends.
- How do you design a C API to reduce dangling pointers? State ownership in function names or documentation, avoid returning pointers to temporary data, prefer caller-owned buffers for outputs, and provide clear create/destroy pairs for heap-owned objects.
Key Takeaways
Dangling pointers are lifetime bugs: the pointer value remains, but the object is gone. The main variants are heap use-after-free, returning local addresses, escaped block-scope addresses, stale aliases, stale pointers after realloc, and owner-lifetime mismatches inside structs or callbacks. Safe C code uses clear ownership, temporary pointers for realloc, deep copies when lifetimes differ, and NULL assignment only as a local safety measure.
For GATE and interviews, the most tested points are the exact meaning of undefined behaviour, the difference between NULL, wild, and dangling pointers, why returning a local variableβs address is invalid, and why aliases remain dangerous after free. Be ready to explain the bug before writing the fix.
The natural next step is Function Pointers in C, because callback-based C programs often combine function pointers with context pointers whose lifetime must be managed carefully.
Further Reading
- Dangling Pointer in C, Additional explanation and examples for revising dangling pointer basics.
- Function Pointers in C, Useful for understanding callbacks, indirection, and pointer syntax in C.
- Function Pointers in C, More practice with function pointer declarations and callback-style usage.
- C++ Pointers, Helpful comparison for learners moving between C memory management and C++ pointer concepts.