GCCでのunordered_map :: insert KeyEqual例外時のメモリリーク-強力な例外安全性保証に違反していますか?


10

私はGCC 7.3.1を使用していますが、coilluでもテストされています。これはバージョン9.2.0だと思います。以下を使用してビルドします。

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

ここにあり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.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).

Visual C ++(Microsoft (R) C/C++ Optimizing Compiler Version 19.24.28314 for x64)でメモリリークが発生しません。

これはunordered_map::inserthttps://stackoverflow.com/a/11699271/1958315)の強力な例外安全性保証に違反しますか?これはGCC STLのバグですか?


STLは、生成できる例外のみをキャッチします(可能な場合)。それはあなたがそれが不変であることを壊すのを防ぐつもりはありません。それについての良いCPPCONトーク:youtube.com/...
NathanOliver

1
@ NathanOliver-ReinstateMonicaおそらくドキュメントを更新する必要がありstd::unordered_map::insertます。「1-4)なんらかの操作によって例外がスローされた場合、挿入は効果がありません。」(強調は私のものです)ここからen.cppreference.com/w/cpp/container/unordered_map/insert
Slava

このプログラムを実行すると、libc ++はメモリをリークしません。
Marshall Clow、

@ NathanOliver-ReinstateMonicaそれはナンセンスです。標準ライブラリは、ユーザーが定義したタイプの例外を処理する必要があります。ここには、不変条件はありません。
ジョナサンウェイクリー

@Raiこれはバグです。gcc.gnu.org/ bugsに報告してください
Jonathan Wakely

回答:


2

標準で義務付けられている保証(最新のドラフトからの引用):

[container.requirements.general]

特に明記されていない限り([associative.reqmts.except]、[unord.req.except]、[deque.modifiers]、および[vector.modifiers]を参照)、この句で定義されているすべてのコンテナタイプは、次の追加要件を満たします。

  • 単一の要素を挿入しているときにinsert()またはemplace()関数によって例外がスローされた場合、その関数は効果がありません。

[associative.reqmts.except]

連想コンテナの場合、単一の要素を挿入する挿入または配置機能内からの操作によって例外がスローされた場合、挿入は効果がありません。

[unord.req.except]

順不同の連想コンテナの場合、単一の要素を挿入する挿入関数または配置関数内からコンテナのハッシュ関数以外の操作によって例外がスローされた場合、挿入は効果がありません。

私が理解している限り、「影響がない」とは「メモリリークがない」ことを意味します。そのような解釈の下では、リークはバグであると考えます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.