Утечка памяти во время исключения unordered_map :: insert KeyEqual с GCC - нарушение строгой гарантии безопасности исключения?

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::insert( https://stackoverflow.com/a/11699271/1958315 )? Это ошибка в GCC STL?

Rai
источник
STL собирает только те исключения, которые он генерирует (если может). Это не защитит вас от взлома, это инвариант. Хороший CPPCON поговорим об этом: youtube.com/…
NathanOliver
1
@ NathanOliver-ReinstateMonica, вероятно, необходимо обновить документацию, как std::unordered_map::insertясно сказано: «1-4) Если исключение выдается какой-либо операцией , вставка не имеет никакого эффекта». (выделение мое) отсюда en.cppreference.com/w/cpp/container/unordered_map/insert
Слава
libc ++ не теряет память при запуске этой программы.
Маршалл Клоу
@ NathanOliver-ReinstateMonica - это чепуха. Стандартная библиотека должна обрабатывать исключения из типов, определенных пользователем. Здесь нет сломанного инварианта.
Джонатан
@ Рай, это ошибка, пожалуйста, сообщите об этом gcc.gnu.org/bugs
Джонатан

Ответы:

2

Гарантия, предусмотренная стандартом (цитаты из последнего проекта):

[Container.requirements.general]

Если не указано иное (см. [Associative.reqmts.except], [unord.req.except], [deque.modifiers] и [vector.modifiers]), все типы контейнеров, определенные в этом разделе, отвечают следующим дополнительным требованиям:

  • если исключение выдается функцией insert () или emplace () при вставке одного элемента, эта функция не имеет эффектов.

[Associative.reqmts.except]

Для ассоциативных контейнеров, если исключение выдается какой-либо операцией из вставки или функции emplace, вставляющей один элемент, вставка не имеет никакого эффекта.

[Unord.req.except]

Для неупорядоченных ассоциативных контейнеров, если исключение выдается какой-либо операцией, отличной от хеш-функции контейнера, изнутри вставки или функции emplace, вставляющей один элемент, вставка не имеет никакого эффекта.

Насколько я понимаю, "не имеет никакого эффекта" подразумевает "отсутствие утечки памяти". При такой интерпретации я бы посчитал утечку ошибкой.

eerorika
источник