У меня есть класс, который управляет контейнером. Моя функция вставки-значения возвращает объект, деструктор которого удаляет вставленное значение. Идея состоит в том, что я могу зарегистрировать значение в контейнере, сохранить полученный объект Registration
, а затем просто вывести этот объект go из области видимости, чтобы удалить зарегистрированное значение. Я уменьшил код проблемного c до следующего:
#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_
как vector
и list
, так и с Directory::registration_t
как shared_ptr
и unique_ptr
.
Я уверен, что должен что-то упустил, но я уже давно смотрю на это и не могу понять, что это такое.