Speicherverlust während unordered_map :: insert KeyEqual-Ausnahme mit GCC - Verletzung der Sicherheitsgarantie für starke Ausnahmen?

10

Ich verwende GCC 7.3.1, habe es aber auch auf coliru getestet, von dem ich glaube, dass es Version 9.2.0 ist. Bauen Sie mit folgendem:

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

Hier ist 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";
    }
}

Das Ausführen führt zu:

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

Ich sehe keine Speicherlecks mit Visual C ++ ( Microsoft (R) C/C++ Optimizing Compiler Version 19.24.28314 for x64).

Verstößt dies gegen die starke Ausnahmesicherheitsgarantie von unordered_map::insert( https://stackoverflow.com/a/11699271/1958315 )? Ist das ein Fehler in der GCC STL?

Rai
quelle
Die STL fängt nur Ausnahmen ab, die sie generiert (wenn dies möglich ist). Es wird nicht davor schützen, dass Sie es brechen, es ist unveränderlich. Gute CPPCON sprechen darüber: youtube.com/…
NathanOliver
1
@ NathanOliver-ReinstateMonica Die Dokumentation muss dann wahrscheinlich aktualisiert werden, da std::unordered_map::insertdeutlich steht: "1-4) Wenn durch eine Operation eine Ausnahme ausgelöst wird , hat das Einfügen keine Auswirkung." (Schwerpunkt liegt bei mir) von hier aus en.cppreference.com/w/cpp/container/unordered_map/insert
Slava
libc ++ verliert beim Ausführen dieses Programms keinen Speicher.
Marshall Clow
@ NathanOliver-ReinstateMonica das ist Unsinn. Die Standardbibliothek muss Ausnahmen von vom Benutzer definierten Typen behandeln. Hier gibt es keine gebrochene Invariante.
Jonathan Wakely
@Rai das ist ein Fehler, bitte melde ihn gcc.gnu.org/bugs
Jonathan Wakely

Antworten:

2

Die vom Standard vorgeschriebene Garantie (Zitate aus dem neuesten Entwurf):

[container.requirements.general]

Sofern nicht anders angegeben (siehe [assoziativ.reqmts.except], [unord.req.except], [deque.modifiers] und [vector.modifiers]), erfüllen alle in dieser Klausel definierten Containertypen die folgenden zusätzlichen Anforderungen:

  • Wenn beim Einfügen eines einzelnen Elements eine Ausnahme von einer Funktion insert () oder emplace () ausgelöst wird, hat diese Funktion keine Auswirkungen.

[assoziative.reqmts.except]

Wenn bei assoziativen Containern eine Ausnahme durch eine Operation innerhalb einer Einfüge- oder Einfügefunktion ausgelöst wird, die ein einzelnes Element einfügt, hat das Einfügen keine Auswirkung.

[unord.req.except]

Wenn bei ungeordneten assoziativen Containern eine Ausnahme durch eine andere Operation als die Hash-Funktion des Containers aus einer Einfüge- oder Einsetzfunktion, die ein einzelnes Element einfügt, ausgelöst wird, hat das Einfügen keine Auswirkung.

Soweit ich weiß, bedeutet "hat keine Wirkung" "kein Speicherverlust". Unter einer solchen Interpretation würde ich ein Leck als Fehler betrachten.

Eerorika
quelle