Compartir a través de


Error: stack-use-after-scope

Error de AddressSanitizer: uso de la memoria de la pila fuera de ámbito

El uso de una dirección de pila fuera del ámbito léxico de la duración de una variable puede producirse de muchas maneras en C o C++.

Ejemplo 1: variable local anidada simple

// 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!
}

Para compilar y probar este ejemplo, ejecute estos comandos en un símbolo del sistema para desarrolladores de Visual Studio 2019 versión 16.9 o posterior:

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

Error resultante: variable local anidada simple

Captura de pantalla del depurador, donde se muestra el error stack-use-after-scope en el ejemplo 1.

Ejemplo 2: captura lambda

// 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!
}

Para compilar y probar este ejemplo, ejecute estos comandos en un símbolo del sistema para desarrolladores de Visual Studio 2019 versión 16.9 o posterior:

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

Error resultante: captura lambda

Captura de pantalla del depurador, donde se muestra el error stack-use-after-scope en el ejemplo 2.

Ejemplo 3: ordenación del destructor con variables locales

// 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;
}

Para compilar y probar este ejemplo, ejecute estos comandos en un símbolo del sistema para desarrolladores de Visual Studio 2019 versión 16.9 o posterior:

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

Error resultante: ordenación del destructor

Captura de pantalla del depurador, donde se muestra el error stack-use-after-scope en el ejemplo 3.

Ejemplo 4: objetos temporales

// 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(); 
}

Para compilar y probar este ejemplo, ejecute estos comandos en un símbolo del sistema para desarrolladores de Visual Studio 2019 versión 16.9 o posterior:

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

ASAN es una forma de análisis dinámico, lo que significa que solo puede detectar código incorrecto que realmente se ejecuta. Un optimizador puede propagar el valor de v en estos casos en lugar de leer de la dirección almacenada en p. Como resultado, este ejemplo requiere la /Od marca .

Error resultante: objetos temporales

Captura de pantalla del depurador, donde se muestra el error stack-use-after-scope en el ejemplo 4.

Consulte también

Introducción a AddressSanitizer
Problemas conocidos de AddressSanitizer
Referencia de lenguaje y compilación de AddressSanitizer
Referencia del entorno de ejecución addressSanitizer
Bytes de sombra addressSanitizer
Pruebas distribuidas o en la nube addressSanitizer
Integración del depurador AddressSanitizer
Ejemplos de errores addressSanitizer