"AddressSanitizer: stack-use-after-scope" 尝试访问指针向量的元素时

"AddressSanitizer: stack-use-after-scope" when trying to access element of vector of pointers

为什么是下面的代码

#include <iostream>
#include <vector>

typedef struct Number {
    int number = 15;
} Number;

int main() {
    std::vector<Number*> nums(5);
    for (size_t i = 0; i < nums.size(); ++i) {
        Number num;
        nums[i] = &num;
    }

    std::cout << nums[1]->number << "\n";

    return 0;
}

触发“AddressSanitizer: stack-use-after-scope”,但是当我评论第 15 行时:std::cout << nums[5]->number << "\n"; 它编译得好吗?如何解决?

编译命令:clang++ main.cpp -fsanitize=address,undefined -fno-sanitize-recover=all -std=c++17 -O2 -Wall -Werror -Wsign-compare -g -o debug_solution && ./debug_solution

问题是您在堆栈上存储了一个指向值的指针,该值超出范围并被销毁,留下悬空指针。

std::vector<Number*> nums(5);
for (size_t i = 0; i < nums.size(); ++i) {
    Number num;
    nums[i] = &num;
    // num goes out of scope here and num[i] has a dangling pointer
    //    to an invalid object
}

std::cout << nums[1]->number << "\n";

在这个玩具示例中,我认为根本没有理由使用指针,解决方法就是使用 std::vector<Number>:

std::vector<Number> nums(5);

// per comment by @user4581301
// this loop is not really needed, as the constuctor will
// default-construct the elements for you
for (size_t i = 0; i < nums.size(); ++i) {
    Number num;
    nums[i] = num;
}

std::cout << nums[1].number << "\n";

如果您确实需要在堆上动态分配内存,您应该考虑使用 std::vector<std::unique_ptr<Number>>std::vector<std::shared_ptr<Number>>,具体取决于对象是否需要在多个组件之间共享。