Skip to content

Latest commit

 

History

History
169 lines (130 loc) · 4.81 KB

error-stack-use-after-scope.md

File metadata and controls

169 lines (130 loc) · 4.81 KB
title description ms.date f1_keywords helpviewer_keywords
Error: stack-use-after-scope
Source examples and live debug screenshots for stack use after scope errors.
02/05/2021
stack-use-after-scope
stack-use-after-scope error
AddressSanitizer error stack-use-after-scope

Error: stack-use-after-scope

Address Sanitizer Error: Use of out-of-scope stack memory

The use of a stack address outside the lexical scope of a variable's lifetime can happen many ways in C or C++.

Example 1 - simple nested local

// example1.cpp
// stack-use-after-scope error
int *gp;

bool b = true;

int main() {
    if (b) {
        int x[5];
        gp = x+1;
    }
    return *gp;  // Boom!
}

To build and test this example, run these commands in a Visual Studio 2019 version 16.9 or later developer command prompt:

cl example1.cpp /fsanitize=address /Zi
devenv /debugexe example1.exe

Resulting error - simple nested local

:::image type="content" source="media/stack-use-after-scope-example-1.png" alt-text="Screenshot of debugger displaying stack-use-after-scope error in example 1.":::

Example 2 - lambda capture

// example2.cpp
// stack-use-after-scope error
#include <functional>

int main() {
    std::function<int()> f;
    {
        int x = 0;
        f = [&x]() {
            return x;  // Boom!
        };
    }
    return f();  // Boom!
}

To build and test this example, run these commands in a Visual Studio 2019 version 16.9 or later developer command prompt:

cl example2.cpp /fsanitize=address /Zi
devenv /debugexe example2.exe

Resulting error - lambda capture

:::image type="content" source="media/stack-use-after-scope-example-2.png" alt-text="Screenshot of debugger displaying stack-use-after-scope error in example 2.":::

Example 3 - destructor ordering with locals

// example3.cpp
// stack-use-after-scope error
#include <stdio.h>

struct IntHolder {
    explicit IntHolder(int* val = 0) : val_(val) { }
    ~IntHolder() {
        printf("Value: %d\n", *val_);  // Bom!
    }
    void set(int* val) { val_ = val; }
    int* get() { return val_; }

    int* val_;
};

int main(int argc, char* argv[]) {
    // It's incorrect to use "x" inside the IntHolder destructor,
    // because the lifetime of "x" ends earlier. Per the C++ standard,
    // local lifetimes end in reverse order of declaration.
    IntHolder holder;
    int x = argc;
    holder.set(&x);
    return 0;
}

To build and test this example, run these commands in a Visual Studio 2019 version 16.9 or later developer command prompt:

cl example3.cpp /fsanitize=address /Zi /O1
devenv /debugexe example3.exe

Resulting error - destructor ordering

:::image type="content" source="media/stack-use-after-scope-example-3.png" alt-text="Screenshot of debugger displaying stack-use-after-scope error in example 3.":::

Example 4 - temporaries

// example4.cpp
// stack-use-after-scope error
#include <iostream>

struct A {
    A(const int& v) {
        p = &v;
    }
    void print() {
        std::cout << *p;
    }
    const int* p;
};

void explicit_temp() {
    A a(5);     // the temp for 5 is no longer live;
    a.print();
}

void temp_from_conversion() {
    double v = 5;
    A a(v);     // local v is no longer live.
    a.print();
}

void main() {
    explicit_temp();
    temp_from_conversion(); 
}

To build and test this example, run these commands in a Visual Studio 2019 version 16.9 or later developer command prompt:

cl example4.cpp /EHsc /fsanitize=address /Zi /Od
devenv /debugexe example4.exe

ASAN is a form of dynamic analysis, which means it can only detect bad code that is actually executed. An optimizer may propagate the value of v in these cases instead of reading from the address stored in p. As a result, this example requires the /Od flag.

Resulting error - temporaries

:::image type="content" source="media/stack-use-after-scope-example-4.png" alt-text="Screenshot of debugger displaying stack-use-after-scope error in example 4.":::

See also

AddressSanitizer overview
AddressSanitizer known issues
AddressSanitizer build and language reference
AddressSanitizer runtime reference
AddressSanitizer shadow bytes
AddressSanitizer cloud or distributed testing
AddressSanitizer debugger integration
AddressSanitizer error examples