Витік пам’яті під час unorряд_map :: вставити виняток 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?


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 - це нісенітниця. Стандартна бібліотека повинна обробляти винятки з типів, які визначає користувач. Тут немає зламаного інваріанта.
Jonathan Wakely

@Rai це помилка, повідомте про це gcc.gnu.org/bugs
Jonathan Wakely

Відповіді:


2

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

[container.requirements.general]

Якщо не вказано інше (див. [Associative.reqmts.except], [unord.req.except], [deque.modifiers] та [vector.modifiers]), всі типи контейнерів, визначені в цьому пункті, відповідають наступним додатковим вимогам:

  • якщо виняток кидається функцією insert () або emplace () під час вставки одного елемента, ця функція не має ефектів.

[Associative.reqmts.except]

Для асоціативних контейнерів, якщо виняток викинуто будь-якою операцією зсередини функції вставки або заміни, яка вставляє один елемент, вставка не впливає.

[unord.req.except]

Для не упорядкованих асоціативних контейнерів, якщо виняток передається будь-якою операцією, окрім хеш-функції контейнера, зсередини вставки або функції заміни, що вставляє один елемент, вставка не впливає.

Наскільки я розумію, "не має ефекту" означає "відсутність витоку пам'яті". За такої інтерпретації я б вважав витік помилкою.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.