Kebocoran memori selama unordered_map :: masukkan pengecualian KeyEqual dengan GCC - melanggar jaminan keamanan pengecualian yang kuat?

10

Saya menggunakan GCC 7.3.1, tetapi juga diuji pada coliru, yang saya percaya adalah versi 9.2.0. Bangun dengan yang berikut:

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

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

Menjalankannya menghasilkan:

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

Saya tidak melihat kebocoran memori dengan Visual C ++ ( Microsoft (R) C/C++ Optimizing Compiler Version 19.24.28314 for x64).

Apakah ini melanggar jaminan keselamatan pengecualian kuat unordered_map::insert( https://stackoverflow.com/a/11699271/1958315 )? Apakah ini bug di GCC STL?

Rai
sumber
STL hanya akan menangkap pengecualian yang dihasilkannya (jika bisa). Itu tidak akan melindungi Anda dari melanggar itu invarian. CPPCON yang baik membicarakannya: youtube.com/...
NathanOliver
1
@ NathanOliver-ReinstateMonica mungkin dokumentasi perlu diperbarui kemudian, dengan std::unordered_map::insertjelas mengatakan "1-4) Jika pengecualian dilemparkan oleh operasi apa pun , penyisipan tidak berpengaruh." (penekanan ada pada saya) dari sini en.cppreference.com/w/cpp/container/unordered_map/insert
Slava
libc ++ tidak membocorkan memori apa pun saat menjalankan program ini.
Marshall Clow
@ NathanOliver-ReinstateMonica itu tidak masuk akal. Pustaka standar harus menangani pengecualian dari jenis yang ditetapkan pengguna. Tidak ada invarian yang rusak di sini.
Jonathan Wakely
@Bai ini bug, tolong laporkan itu gcc.gnu.org/bugs
Jonathan Wakely

Jawaban:

2

Jaminan yang diamanatkan oleh standar (kutipan dari konsep terbaru):

[container.requirements.general]

Kecuali ditentukan lain (lihat [associative.reqmts.except], [unord.req.except], [deque.modifiers], dan [vector.modifiers]) semua jenis wadah yang ditentukan dalam Klausul ini memenuhi persyaratan tambahan berikut:

  • jika pengecualian dilemparkan oleh fungsi insert () atau emplace () saat memasukkan elemen tunggal, fungsi itu tidak memiliki efek.

[associative.reqmts.except]

Untuk wadah asosiatif, jika pengecualian dilemparkan oleh operasi apa pun dari dalam fungsi insert atau emplace memasukkan elemen tunggal, insersi tidak memiliki efek.

[unord.req.except]

Untuk wadah asosiatif yang tidak berurutan, jika pengecualian dilemparkan oleh operasi apa pun selain fungsi hash penampung dari dalam insert atau fungsi emplace memasukkan elemen tunggal, insersi tidak memiliki efek.

Sejauh yang saya mengerti, "tidak memiliki efek" menyiratkan "tidak ada kebocoran memori". Di bawah interpretasi seperti itu, saya akan menganggap kebocoran sebagai bug.

eerorika
sumber