4

いくつかのライブラリを msvc から mingw に移動し始め、アップキャストされたオブジェクトの配列を削除したい場合の msvc の非常に興味深い動作を発見しました。つまり、msvc はいくつかのダーク マジックを実行し (それを行うのが好きなようです)、次のコードは正常に実行されますが、mingw では (4.7.2( がクラッシュします。mingw は正しく実行されていると思います。スリーパーバグ。

コード:

#include <iostream>

class foo{
    static int idgen;
protected:
    int id;
public:
    foo(){
        id = idgen++;
        std::cout << "Hello  ( foo - "<<id<<")"<<std::endl;
    }
    virtual ~foo(){
        std::cout << "Bye bye ( foo - "<<id<<")"<<std::endl;
    };
};

int foo::idgen = 0;


class bar: public foo{
    double some_data[20];
public:
    bar(){

    std::cout << "Hello  ( bar - "<<id<<")"<<std::endl;
}
    ~bar(){
        std::cout << "Bye bye ( bar - "<<id<<")"<<std::endl;
    }
};

int main()
{
    const unsigned int size = 2;
    foo** arr = new foo*[size];
    {
        bar* tmp = new bar[size];
        for(int i=0; i<size; i++)
        {
            arr[i] = &(tmp[i]); //take address of each object
        }
    }

    delete [] arr[0]; //take address of first object, pointer is same as tmp. This also crashes mingw
    delete [] arr;

}

msvc 2010 からの出力

Hello  ( foo - 0)
Hello  ( bar - 0)
Hello  ( foo - 1)
Hello  ( bar - 1)
Bye bye ( bar - 1)
Bye bye ( foo - 1)
Bye bye ( bar - 0)
Bye bye ( foo - 0)

そしてmingw(破壊時に墜落)

Hello  ( foo - 0)
Hello  ( bar - 0)
Hello  ( foo - 1)
Hello  ( bar - 1) 

私の質問は、これを修正するための正しいアプローチは何ですか。私が思いついた現在のハックフィックスには、可能なすべてのクラスにダウンキャストしようとし、ダウンキャストされたポインターで削除操作を呼び出すだけでした。

if(dynamic_cast<bar*>(arr[0]) != 0)
    delete [] dynamic_cast<bar*>(arr[0]); 

ライブラリを再設計する以外に、より良いアプローチはありますか (それは私のものではありません)。

4

2 に答える 2

1

ここの簡単な例でも gcc 4.7.2 は失敗します -> ideone.com/z876QX#view_edit_box したがって、配列の場合、仮想デストラクタを使用できないようです。

const unsigned int size = 2;
foo* test = new bar[size];
delete[] test;

deleteただし、の代わりに使用できるポインターの配列を使用すると、回避できますdelete[]

http://ideone.com/NfbF3n#view_edit_box

const int size = 5;
foo *test[size];
for(int i = 0; i < size; ++i)
    test[i] = new bar;
for(int i = 0; i < size; ++i)
   delete test[i];
于 2013-05-15T23:38:03.400 に答える