Aracılığıyla paylaş


Hata: stack-use-after-return

Adres Temizleme Hatası: Dönüş sonrasında yığın belleği kullanımı

Bu denetim, /fsanitize-address-use-after-returnek bir derleyici seçeneği tarafından ve ortam değişkeni ASAN_OPTIONS=detect_stack_use_after_return=1ayarlanarak etkinleştirilen kod oluşturmayı gerektirir.

Bu denetim uygulamanızı önemli ölçüde yavaşlatabilir. Geri dönüş sonrasında kullanımı destekleyen algoritmanın Clang özetini ve daha yüksek performans maliyetlerini göz önünde bulundurun.

Önemli

Ek derleyici seçeneğini /fsanitize-address-use-after-returnkullanarak bir nesne dosyası oluşturursanız, derleyici tarafından oluşturulan kod bir yığın çerçevesinin nasıl ayrılacağı konusunda çalışma zamanı kararı verir. Ortam değişkeni ASAN_OPTIONS olarak detect_stack_use_after_returnayarlı değilse, kod yine de kendi başına kullanmaktan /fsanitize=address daha yavaştır. Kullanarak alloca()bir çerçevenin bölümleri için alan ayıran bazı yığın çerçevelerinin ek yükü olduğundan daha yavaştır. Dönüş sonrası kullanım hatalarını işlemeyi bitirdiğinizde bu nesne dosyalarını silmek en iyisidir.

Örnek - Basit C

// example1.cpp
// stack-use-after-return error
volatile char* x;

void foo() {
    char stack_buffer[42];
    x = &stack_buffer[13];
}

int main() {

    foo();
    *x = 42; // Boom!

    return (*x == 42);
}

Bu örneği derlemek ve test etmek için visual studio 2019 sürüm 16.9 veya sonraki bir geliştirici komut isteminde şu komutları çalıştırın:

cl example1.cpp /fsanitize=address /fsanitize-address-use-after-return /Zi
set ASAN_OPTIONS=detect_stack_use_after_return=1
devenv /debugexe example1.exe

Sonuç hatası - Basit C

Örnek 1'de stack-use-after-return hatasını görüntüleyen hata ayıklayıcının ekran görüntüsü.

Örnek - C++ ve şablonlar

// example2.cpp
// stack-use-after-return error
#include <stdlib.h>

enum ReadOrWrite { Read = 0, Write = 1 };

struct S32 {
    char x[32];
};

template<class T>
T* LeakStack() {
    T t[100];
    static volatile T* x;
    x = &t[0];
    return (T*)x;
}

template<class T>
void StackUseAfterReturn(int Idx, ReadOrWrite w) {
    static T sink;
    T* t = LeakStack<T>();
    if (w)
        t[100 + Idx] = T();
    else
        sink = t[100 + Idx];
}

int main(int argc, char* argv[]) {

    if (argc != 2) return 1;
    int kind = atoi(argv[1]);

    switch (kind) {
    case 1: StackUseAfterReturn<char>(0, Read); break;
    case 2: StackUseAfterReturn<S32>(0, Write); break;
    }
    return 0;
}

Bu örneği derlemek ve test etmek için visual studio 2019 sürüm 16.9 veya sonraki bir geliştirici komut isteminde şu komutları çalıştırın:

cl example2.cpp /fsanitize=address /fsanitize-address-use-after-return /Zi /Od
set ASAN_OPTIONS=detect_stack_use_after_return=1
devenv /debugexe example2.exe 1

ASAN bir dinamik analiz biçimidir, yani yalnızca gerçekte yürütülen hatalı kodu algılayabilir. İyileştirici, veya sink değerinin t[100 + Idx] hiçbir zaman kullanılmadığını belirleyebilir ve atamayı ilerletebilir. Sonuç olarak, bu örnek bayrağı gerektirir /Od .

Sonuç hatası - C++ ve şablonlar

Örnek 2'de stack-use-after-return hatasını görüntüleyen hata ayıklayıcının ekran görüntüsü.

Ayrıca bkz.

AddressSanitizer'a genel bakış
AddressSanitizer bilinen sorunları
AddressSanitizer derlemesi ve dil başvurusu
AddressSanitizer çalışma zamanı başvurusu
AddressSanitizer gölge baytları
AddressSanitizer bulut veya dağıtılmış test
AddressSanitizer hata ayıklayıcısı tümleştirmesi
AddressSanitizer hata örnekleri