gpt4 book ai didi

c++ - 为什么 AddressSanitizer 报告堆栈使用后作用域错误?

转载 作者:行者123 更新时间:2023-12-02 10:05:28 31 4
gpt4 key购买 nike

我有一个管理容器的类。我的 insert-a-value 函数返回一个对象,其析构函数删除了插入的值。这个想法是我可以在容器中注册一个值,保存结果 Registration对象,然后让该对象超出范围以删除注册值。我已将有问题的代码简化为以下内容:

#include <iostream>
#include <list>
#include <vector>
#include <memory>
#include <string>
#include <unordered_map>

class Directory {
public:
struct Registration {
Registration(Directory& dir, const std::string& key)
: dir_{dir}, key_{key}
{}

~Registration() { dir_.del(key_); }

Directory& dir_;
const std::string& key_;
};

using registration_t = std::unique_ptr<Registration>;

registration_t put(std::string key, std::string val) {
map_[key] = val;
return std::make_unique<Registration>(*this, key);
}

void del(const std::string& key) {
map_.erase(key);
}

private:
std::unordered_map<std::string,std::string> map_;
};

int main(int argc, char* argv[])
{
Directory directory_;
std::list<typename Directory::registration_t> registrations_;

registrations_.push_back(directory_.put("asdf", "djdjdjdjd"));

for ( const auto& i: registrations_ )
std::cout << i->key_ << std::endl;
}

当我使用 AddressSanitizer 运行它时,它报告以下内容:
=================================================================
==153498==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7ffcb33622e0 at pc 0x7fb29b24a2fd bp 0x7ffcb3362140 sp 0x7ffcb33618e8
READ of size 4 at 0x7ffcb33622e0 thread T0
#0 0x7fb29b24a2fc (/lib64/libasan.so.5+0x6a2fc)
#1 0x7fb29b116082 in std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) (/lib64/libstdc++.so.6+0x136082)
#2 0x402826 in main /home/john/asdf/test.cpp:43
#3 0x7fb29accf1a2 in __libc_start_main ../csu/libc-start.c:308
#4 0x4023dd in _start (/home/john/asdf/a.out+0x4023dd)

Address 0x7ffcb33622e0 is located in stack of thread T0 at offset 240 in frame
#0 0x4024a5 in main /home/john/asdf/test.cpp:37

This frame has 9 object(s):
[32, 33) '<unknown>'
[48, 49) '<unknown>'
[64, 72) '<unknown>'
[96, 104) '__for_begin' (line 42)
[128, 136) '__for_end' (line 42)
[160, 184) 'registrations_' (line 39)
[224, 256) '<unknown>' <== Memory access at offset 240 is inside this variable
[288, 320) '<unknown>'
[352, 408) 'directory_' (line 38)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope (/lib64/libasan.so.5+0x6a2fc)
Shadow bytes around the buggy address:
0x100016664400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100016664410: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100016664420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100016664430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1
0x100016664440: f1 f1 f8 f2 f8 f2 f8 f2 f2 f2 00 f2 f2 f2 00 f2
=>0x100016664450: f2 f2 00 00 00 f2 f2 f2 f2 f2 f8 f8[f8]f8 f2 f2
0x100016664460: f2 f2 f8 f8 f8 f8 f2 f2 f2 f2 00 00 00 00 00 00
0x100016664470: 00 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00
0x100016664480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100016664490: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000166644a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

如果 directory_ 似乎没有关系和 registrations_是本地的 main()或全局。我已经尝试过 registrations_作为 vectorlist ,并与 Directory::registration_t作为 shared_ptr和一个 unique_ptr .

我确定我一定遗漏了一些东西,但我已经盯着这个看了一段时间,无法弄清楚它是什么。

最佳答案

Directory::put函数需要 key按值,然后存储对此对象的引用。

这不会很好地工作,因为对象 key一旦put 将被破坏并不复存在函数返回。任何使用此悬空引用的尝试都将导致未定义的行为。

Registration 中存储拷贝类代替。

关于c++ - 为什么 AddressSanitizer 报告堆栈使用后作用域错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60390201/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com