Vazamento de memória durante a exceção unordered_map :: insert KeyEqual no GCC - quebrando a forte garantia de segurança de exceções?

10

Estou usando o GCC 7.3.1, mas também testei no coliru, que acredito ser a versão 9.2.0. Crie com o seguinte:

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

Aqui está 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 execução resulta em:

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

Não vejo vazamentos de memória no Visual C ++ ( Microsoft (R) C/C++ Optimizing Compiler Version 19.24.28314 for x64).

Isso quebra a forte garantia de segurança de exceção de unordered_map::insert( https://stackoverflow.com/a/11699271/1958315 )? Isso é um bug no GCC STL?

Rai
fonte
O STL apenas captura exceções que gera (se puder). Não vai se proteger contra você quebrá-lo invariável. Bom CPPCON falar sobre isso: youtube.com/…
NathanOliver
11
@ NathanOliver-ReinstateMonica provavelmente a documentação precisa ser atualizada, como std::unordered_map::insertdiz claramente "1-4) Se uma exceção for lançada por qualquer operação , a inserção não terá efeito." (ênfase é minha) a partir daqui en.cppreference.com/w/cpp/container/unordered_map/insert
Slava
A libc ++ não vaza memória ao executar este programa.
Marshall Clow
@ NathanOliver-ReinstateMonica isso é um absurdo. A biblioteca padrão precisa lidar com exceções dos tipos que o usuário define. Não há invariável quebrado aqui.
Jonathan Wakely
@Rai isso é um bug, por favor, reporte-o gcc.gnu.org/bugs
Jonathan Wakely

Respostas:

2

A garantia exigida pela norma (citações do último rascunho):

[container.requirements.general]

Salvo especificação em contrário (consulte [associative.reqmts.except], [unord.req.except], [deque.modifiers] e [vector.modifiers]) todos os tipos de contêineres definidos nesta Cláusula atendem aos seguintes requisitos adicionais:

  • se uma exceção for lançada por uma função insert () ou emplace () ao inserir um único elemento, essa função não terá efeito.

[associative.reqmts.except]

Para contêineres associativos, se uma exceção for lançada por qualquer operação de uma função de inserção ou substituição inserindo um único elemento, a inserção não terá efeito.

[unord.req.except]

Para contêineres associativos não ordenados, se uma exceção for lançada por qualquer operação que não seja a função hash do contêiner de dentro de uma função de inserção ou substituição, inserindo um único elemento, a inserção não terá efeito.

Tanto quanto eu entendo, "não tem efeito" implica "sem vazamento de memória". Sob essa interpretação, consideraria um vazamento um bug.

eerorika
fonte