10

I'm using GCC 7.3.1, but also tested on coliru, which I believe is version 9.2.0. Build with the following:

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

Here's 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";
    }
}

Running it results in:

> ./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).

I don't see any memory leaks with Visual C++ (Microsoft (R) C/C++ Optimizing Compiler Version 19.24.28314 for x64).

Does this break the strong exception safety guarantee of unordered_map::insert (https://stackoverflow.com/a/11699271/1958315)? Is this a bug in the GCC STL?

4

1 回答 1

2

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

[container.requirements.general]

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

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

[associative.reqmts.except]

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

[unord.req.except]

对于无序关联容器,如果在插入单个元素的 insert 或 emplace 函数中除容器的散列函数之外的任何操作引发异常,则插入无效。

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

于 2019-12-12T15:05:07.393 回答