Bagikan melalui


Kesalahan: stack-use-after-scope

Kesalahan Pembersih Alamat: Penggunaan memori tumpukan di luar cakupan

Penggunaan alamat tumpukan di luar cakupan leksikal masa pakai variabel dapat terjadi banyak cara di C atau C++.

Contoh 1 - lokal berlapis sederhana

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

Untuk membuat dan menguji contoh ini, jalankan perintah ini di perintah Visual Studio 2019 versi 16.9 atau yang lebih baru:

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

Kesalahan yang dihasilkan - lokal berlapis sederhana

Cuplikan layar debugger yang menampilkan kesalahan stack-use-after-scope dalam contoh 1.

Contoh 2 - penangkapan 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!
}

Untuk membuat dan menguji contoh ini, jalankan perintah ini di perintah Visual Studio 2019 versi 16.9 atau yang lebih baru:

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

Kesalahan yang dihasilkan - penangkapan lambda

Cuplikan layar debugger yang menampilkan kesalahan stack-use-after-scope dalam contoh 2.

Contoh 3 - pemesanan destruktor dengan penduduk lokal

// 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_);  // Boom!
    }
    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;
}

Untuk membuat dan menguji contoh ini, jalankan perintah ini di perintah Visual Studio 2019 versi 16.9 atau yang lebih baru:

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

Mengakibatkan kesalahan - pengurutan destruktor

Cuplikan layar debugger yang menampilkan kesalahan stack-use-after-scope dalam contoh 3.

Contoh 4 - sementara

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

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

Untuk membuat dan menguji contoh ini, jalankan perintah ini di perintah Visual Studio 2019 versi 16.9 atau yang lebih baru:

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

ASAN adalah bentuk analisis dinamis, yang berarti hanya dapat mendeteksi kode buruk yang benar-benar dijalankan. Pengoptimal dapat menyebarluaskan nilai v dalam kasus ini alih-alih membaca dari alamat yang disimpan di p. Akibatnya, contoh ini memerlukan /Od bendera.

Kesalahan yang dihasilkan - sementara

Cuplikan layar debugger yang menampilkan kesalahan stack-use-after-scope dalam contoh 4.

Lihat juga

Gambaran umum AddressSanitizer
Masalah yang diketahui AddressSanitizer
Referensi bahasa dan build AddressSanitizer
Referensi runtime AddressSanitizer
Byte bayangan AddressSanitizer
AddressSanitizer cloud atau pengujian terdistribusi
Integrasi debugger AddressSanitizer
Contoh kesalahan AddressSanitizer