3

私は、Bjarne Stroustrup の本「The C++ Programming Language」のすべての演習に取り組んできました。

私が困惑した 1 つの特定の演習(E.8.4)にたどり着きました。
これは、標準ライブラリ クラスでの例外の安全性について説明する付録です。 . 彼はベクトルのコンストラクターの可能な実装の 1 つを示してから、読者にエラーを見つけるように求めます. ヒントは、それがデストラクタと関係があることを示しています (おそらく二重解放?) しかし、私は彼が何を求めているのかわかりません.

私が知る限り、アロケーターは bad_alloc をスローして ctor を終了させる可能性があります。同様に、T のコピー ctor は uninitialized_fill 内でスローする可能性があり、これにより、以前にコピーされた要素が破棄され、ctor が終了します。そこにエラーがある場合、それは私には明らかではありません。

演習は次のように表現されます: 「ベクターのコンストラクター(E.3.1)の「乱雑な」バージョンでエラーを見つけ、それをクラッシュさせるプログラムを作成します。ヒント:最初にベクターのデストラクタを実装します。

これは 1 ポイントの演習にすぎないため、ばかげて明らかな何かを見逃しているに違いありません。その場合、すべての賭けがオフになるため、デストラクタのスローとは何の関係もないと思います。「スペース」と「最後」のフィールドで不変条件を維持するのに問題があるのではないでしょうか?

誰かのアイデアを聞きたいです。

関連するコードは次のとおりです。

template<class T, class A = std::allocator<T> >
class vector {
private:
    T* v;
    T* space;
    T* last;
    A alloc;

    void destroy_all();
public:
    typedef size_t size_type;

    explicit vector(size_type n, const T& val = T(), const A& = A());
    vector(const vector& a);
    vector& operator=(const vector& a);
    ~vector() { destroy_all(); alloc.deallocate(v, last-v); }
    size_type size() const { return space-v; }
    size_type capacity() const { return last-v; }
    void push_back(const T&);
};

template<class T, class A>
void vector<T,A>::destroy_all() {
    for(T* p = v; p != last; p++)
        alloc.destroy(p);
}

template<class T, class A>
vector<T,A>::vector(size_type n, const T& val, const A& a) : alloc(a) {
    v = alloc.allocate(n);
    try {
        std::uninitialized_fill(v, v + n, val);
        space = last = v + n;
    }
    catch(...) {
        alloc.deallocate(v, n);
        throw;
    }
}
4

2 に答える 2

0

問題は、コンストラクターTがスローできることです。つまり、これがスローされる可能性があります。

std::uninitialized_fill(v, v + n, val);

その場合、句は、すでに構築されている可能性のあるオブジェクトをcatch(...)適切に破棄することなく、メモリの割り当てを解除します。T

于 2012-09-05T03:23:34.690 に答える
0

allocator::allocate投げることができstd::bad_allocます。その場合、初期化さvれておらず、メモリ不足から回復したとしても、破壊時にセグメンテーション違反が発生します。

もう 1 つの問題はstd::initialized_fillです。スローされた場合は、データ ポインターを無効としてマークせずに内部ストレージを解放します。デストラクタは同じメモリを再び解放します。

于 2012-10-13T13:18:50.290 に答える