October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk5 min

Why a Pointer to a Local C Struct Can Segfault—and How to Fix It

Returning or saving a pointer to a local C struct does not extend the struct’s lifetime. Understand why the code can seem to work, and choose a safe ownership pattern.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A pointer to a local struct becomes invalid when the block containing that struct ends. Returning or saving the pointer does not extend the struct’s lifetime, so later access has undefined behavior: it may crash, appear to work, or fail differently after other code runs. Passing a pointer is not inherently unsafe; the key is whether the pointed-to object remains alive for as long as it is used.

What makes a pointer to a local struct invalid?

Consider a function that creates a struct with automatic storage duration and returns its address:

As an Amazon Associate I earn from qualifying purchases.

struct Config {
    int mode;
};

struct Config *make_config(void) {
    struct Config config = { .mode = 1 };
    return &config;
}

The object config exists only while execution is within its block. When make_config returns, that block ends and the object’s lifetime ends. The returned pointer still contains an address, but it no longer designates a live struct Config. CERT C Rule DCL30-C states: “The address of an object with automatic storage shall not be returned from a function.” CERT C Rule DCL30-C

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

C describes the object’s storage duration and lifetime; it does not require that every automatic object physically reside on a machine stack. The important issue is the lifetime rule, not where a particular compiler puts the bytes.

Why it may not crash right away

Using a pointer after the target’s lifetime ends is invalid even if a test run prints the expected value. The old bytes may remain unchanged temporarily, then be reused by later calls or other activity. As a result, the behavior can vary with call sequence, optimization, and platform. A segmentation fault is one possible symptom, not a guaranteed outcome or the definition of the bug. CERT C Rule DCL30-C C storage duration reference

Do not try to fix this by guessing how long the address will remain usable or by relying on a particular stack layout. The object’s lifetime has ended; the correct fix is to choose storage whose lifetime matches how long the result is needed.

When passing a pointer is safe

A function may safely receive a pointer to a struct that its caller owns, provided the object stays alive throughout the function’s use of it:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
struct Config {
    int mode;
};

void initialize_config(struct Config *out) {
    out->mode = 1;
}

int main(void) {
    struct Config config;
    initialize_config(&config);
    /* config remains alive here */
    return config.mode;
}

Here, config belongs to the caller and remains alive after initialize_config returns. The risk arises if a function stores or returns a pointer to its own local object and some code uses that pointer after the function exits. CERT’s recommended approach for persistent output is to declare the object in the scope that needs it and pass its address to the initializer. CERT C Rule DCL30-C CERT C Rule EXP35-C

Choose an ownership pattern that fits the result

Before choosing a repair, decide who owns the object, how long it must live, whether separate calls need independent results, and—if memory is allocated dynamically—who releases it.

Use caller-owned output storage

Have the caller create the struct and pass its address to a function that fills it. This is a straightforward choice when the caller needs the result to remain available in its own scope:

void make_config(struct Config *out) {
    out->mode = 1;
}

int main(void) {
    struct Config config;
    make_config(&config);
    return config.mode;
}

The caller controls the object’s lifetime, and each caller can provide a different object when independent results are needed. The function must not retain the pointer and use it after the caller’s object has ceased to exist.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Return a struct by value

If a function naturally produces one struct value, it can return that value instead of returning a pointer to a local:

struct Config make_config(void) {
    struct Config config = { .mode = 1 };
    return config;
}

Returning a struct value is a different operation from returning &config: the caller receives a value, not a pointer to the callee’s expired local object. Whether this interface is suitable depends on the program’s design and the struct’s use; there is no need to assume a particular machine-level implementation of the return. C return statement reference

Allocate when the object needs a dynamic lifetime

Dynamic allocation is appropriate when the object must outlive the function and its lifetime cannot conveniently be tied to a caller-owned local. Return the allocation’s pointer, document who owns it, and establish who frees it:

#include <stdlib.h>

struct Config *make_config(void) {
    struct Config *config = malloc(sizeof *config);
    if (config == NULL) {
        return NULL;
    }
    config->mode = 1;
    return config;
}

/* The receiving owner eventually calls free(config). */

Unlike an automatic local, allocated storage remains available until it is deallocated. The allocation must be checked for failure, and the program needs a clear ownership rule so that the object is freed exactly when it is no longer needed. C malloc reference

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use static storage only when sharing is intended

A static object lasts for the program’s execution, so returning its address does not create the same expired-local problem. But a function-local static is shared across calls: a later call can overwrite the value observed through an earlier returned pointer. That makes it unsuitable when callers need independent results and can complicate reentrant or concurrent use. Static storage is a design choice for intentionally shared state, not a universal lifetime fix. C storage duration reference

Best Value
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

How to find dangling-pointer mistakes

GCC 16.1 documents -Wdangling-pointer for diagnostics involving pointers to automatic objects used after their lifetime ends. Its documented cases include an address escaping through a pointer parameter. Enable the warning in builds where that GCC version is used, then investigate each diagnostic in context. A warning can help reveal a bug, but no warning does not prove that every pointer is valid. GCC 16.1 warning options

A separate temporary-struct lifetime edge case

Not every lifetime bug involves returning the address of a named local variable. CERT C Rule EXP35-C also discusses pointers to array members of temporary struct or union expressions: in the covered cases, using the array after the temporary’s lifetime expires is undefined behavior. This is a related lifetime issue, but it is distinct from the simpler case of returning the address of a named local struct. CERT C Rule EXP35-C

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.