Wyciek pamięci podczas unordered_map :: wstaw wyjątek KeyEqual z GCC - przełamanie silnej gwarancji bezpieczeństwa wyjątku?

10

Korzystam z GCC 7.3.1, ale testowałem również na coliru, które moim zdaniem to wersja 9.2.0. Kompiluj za pomocą:

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

Oto 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";
    }
}

Uruchomienie powoduje:

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

Nie widzę żadnych przecieków pamięci w Visual C ++ ( Microsoft (R) C/C++ Optimizing Compiler Version 19.24.28314 for x64).

Czy to łamie silną wyjątkową gwarancję bezpieczeństwa unordered_map::insert( https://stackoverflow.com/a/11699271/1958315 )? Czy to błąd w GCC STL?

Rai
źródło
STL będzie przechwytywał tylko generowane przez siebie wyjątki (jeśli to możliwe). Nie ochroni cię przed złamaniem, jest niezmienny. Dobra rozmowa CPPCON na ten temat: youtube.com/…
NathanOliver
1
@ NathanOliver-ReinstateMonica prawdopodobnie należy zaktualizować dokumentację, jak to std::unordered_map::insertwyraźnie stwierdza „1-4) Jeśli jakakolwiek operacja spowoduje wyjątek , wstawienie nie ma wpływu”. (nacisk jest mój) stąd en.cppreference.com/w/cpp/container/unordered_map/insert
Slava
libc ++ nie przecieka pamięci podczas uruchamiania tego programu.
Marshall Clow,
@ NathanOliver-ReinstateMonica to nonsens. Biblioteka standardowa musi obsługiwać wyjątki od typów zdefiniowanych przez użytkownika. Tutaj nie ma zepsutego niezmiennika.
Jonathan Wakely
@ Rai to jest błąd, zgłoś go gcc.gnu.org/bugs
Jonathan

Odpowiedzi:

2

Gwarancja wymagana przez standard (cytaty z najnowszego projektu):

[container.requirements.general]

O ile nie określono inaczej (patrz [Associative.reqmts.except], [unord.req.except], [deque.modifiers] i [vector.modifiers]) wszystkie typy kontenerów zdefiniowane w niniejszej klauzuli spełniają następujące dodatkowe wymagania:

  • jeśli wyjątek zostanie zgłoszony przez funkcję insert () lub Situace () podczas wstawiania pojedynczego elementu, funkcja ta nie ma wpływu.

[Associative.reqmts.except]

W przypadku kontenerów asocjacyjnych, jeśli wyjątek zostanie zgłoszony przez dowolną operację z funkcji wstawiania lub funkcji umieszczania wstawiającej pojedynczy element, wstawianie nie ma wpływu.

[unord.req.except]

W przypadku nieuporządkowanych kontenerów asocjacyjnych, jeśli wyjątek zostanie zgłoszony przez dowolną operację inną niż funkcja skrótu kontenera z funkcji wstawiania lub funkcji umieszczania wstawiającej pojedynczy element, wstawianie nie ma wpływu.

O ile rozumiem, „nie ma wpływu” oznacza „brak wycieku pamięci”. Według takiej interpretacji wyciek uważałbym za błąd.

eerorika
źródło