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?


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.