在使用GCC的unordered_map :: insert KeyEqual异常期间发生内存泄漏-破坏了强有力的异常安全保证吗?


10

我正在使用GCC 7.3.1,但也在coliru(我相信它是9.2.0版)上进行了测试。使用以下内容进行构建:

g++ -fsanitize=address -fno-omit-frame-pointer rai.cpp

这里是rai.cpp

#include <iostream>
#include <unordered_map>

int main()
{
    try
    {
        struct MyComp {
            bool operator()(const std::string&, const std::string&) const {
                throw std::runtime_error("Nonono");
            }
        };

        std::unordered_map<std::string, std::string, std::hash<std::string>, MyComp> mymap;
        mymap.insert(std::make_pair("Hello", "There"));
        mymap.insert(std::make_pair("Hello", "There")); // Hash match forces compare
    } catch (const std::exception& e) {
        std::cerr << "Caught exception: " << e.what() << "\n";
    }
}

运行它会导致:

> ./a.out
Caught exception: Nonono

=================================================================
==72432==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 32 byte(s) in 1 object(s) allocated from:
...

Direct leak of 4 byte(s) in 1 object(s) allocated from:
...

Indirect leak of 60 byte(s) in 2 object(s) allocated from:
...

SUMMARY: AddressSanitizer: 96 byte(s) leaked in 4 allocation(s).

我看不到Visual C ++有任何内存泄漏(Microsoft (R) C/C++ Optimizing Compiler Version 19.24.28314 for x64)。

这是否会破坏unordered_map::inserthttps://stackoverflow.com/a/11699271/1958315)的强大异常安全保证?这是GCC STL中的错误吗?


STL仅会捕获其生成的异常(如果可以)。它不会防止您破坏它的不变性。好的CPPCON谈论它:youtube.com/…–
NathanOliver

1
@ NathanOliver-ReinstateMonica可能需要然后更新文档,std::unordered_map::insert很明显地说:“ 1-4)如果任何操作抛出异常,则插入无效。” (强调是我的),来自此处en.cppreference.com/w/cpp/container/unordered_map/insert
Slava

运行该程序时,libc ++不会泄漏任何内存。
马歇尔·科洛

@ NathanOliver-ReinstateMonica这是胡说八道。标准库必须处理用户定义类型的异常。这里没有破碎的不变式。
乔纳森·韦克里

@Rai这是一个错误,请报告它gcc.gnu.org/bugs
Jonathan Wakely

Answers:


2

该标准规定的保证(引自最新草案):

[container.requirements.general]

除非另有说明(请参阅[associative.reqmts.except],[unord.req.except],[deque.modifiers]和[vector.modifiers]),否则本条款中定义的所有容器类型均满足以下附加要求:

  • 如果在插入单个元素时insert()或emplace()函数引发异常,则该函数无效。

[associative.reqmts.except]

对于关联容器,如果插入单个元素的insert或emplace函数中的任何操作均引发异常,则该插入无效。

[unord.req.except]

对于无序关联容器,如果从插入单个元素的insert或emplace函数内部,除了容器的hash函数以外的任何操作都引发了异常,则插入无效。

据我了解,“没有效果”意味着“没有内存泄漏”。根据这种解释,我认为泄漏是一个错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.