1

ある動的ライブラリで割り当てられたメモリが別のライブラリで削除されると、dll 境界を越えたメモリの割り当てと割り当て解除で示されるように、問題が発生することがよくあります。私の質問は auto_ptr タイプのオブジェクトに関連しています。dll によって提供されるこのタイプのオブジェクトは、dll を使用するプログラムがオブジェクトを自動的に削除するため、非常に注意が必要です。ただし、DLL ライブラリ内の auto_ptr タイプのオブジェクトに対して、一部のメモリ再割り当て操作が発生することがよくあります。したがって、auto_ptr 型のオブジェクトを破棄する関数を記述する必要があります。まず、dll ライブラリ内の auto_ptr タイプのオブジェクトを破棄することの重要性を示す次の例を示します。

.dll ライブラリのヘッダー ファイルは次のとおりです。

dll.h
class __declspec(dllexport) Image
{
public:
    Image()
    {
        mem = NULL;
    }
    ~Image()
    {
        std::cout<<"Image is being deleted!"<<std::endl;

        delete []mem;
        mem = NULL;

    }

    int *mem;

};

typedef std::auto_ptr<Image> ImagePtr;



class __declspec(dllexport) ImageReader
{
public:
    void memory_reset(Image &img)
    {
img.mem = new int [20*30];

    }
};

dll ライブラリを呼び出す実行可能プログラムは次のとおりです。

#include "dll.h"
#include <iostream>
#include <vector>
#include <numeric>
#include <iostream>
#include <algorithm>
#include <functional>
#include <iterator>

int main()
{
    ImagePtr my_img(new Image());
    ImageReader bmp_reader;
    bmp_reader.memory_reset(*my_img);

    return 0;

}

呼び出されたランタイム ライブラリが静的にリンクされている場合 ( Multi-threaded Debug (/MTd))、実行可能プログラムの実行時にエラーが発生します。 ここに画像の説明を入力

この問題を解決するには、auto_ptr オブジェクトをライブラリで削除する必要があります。次に疑問が生じます: このタイプのオブジェクトを削除する最善の方法は何ですか? 私が考えることができる方法は、auto_ptr オブジェクトを削除できるグローバル関数を提供することです。

void Fun_destroy_memory(Image &img)
{
    img.~Image();
}

したがって、実行可能プログラムは次のようになります。

int main()
{
    ImagePtr my_img(new Image());
    ImageReader bmp_reader;
    bmp_reader.memory_reset(*my_img);
    Fun_destroy_memory(*my_img);

    return 0;

}   

この状況で他の解決策があるかどうかはわかりません。さらに、私がFun_destroy_memory. どうもありがとう!

4

1 に答える 1

2

auto_ptrs は、それらが表すオブジェクトの管理を担当します。それらが管理しているオブジェクトは、auto_ptr がスコープ外になると解放されます。「new」で作成しない変数の「ライフタイム」を制御することはできません。そのため、この「auto_ptr」を破棄する方法はなく、単に範囲外になります。このオブジェクトにスコープの問題があり、これが問題であると確信している場合 (明らかに私には確信が持てません)、コードのセクションを任意のスコープ解決演算子でアウトライン化して、特定の変数のスコープを管理できます。あなたのコードをコピーして例を作成しました。

int main()
{
    //Do some work that doesn't need an ImagePtr
    ImageReader bmp_reader;
    { 
        ImagePtr my_img(new Image());
        bmp_reader.memory_reset(*my_img);
    } // the my_img pointer is no longer in scope and it's manage object will be freed          
    return 0;
}

これを行うことを必ずしもお勧めするわけではないことに注意してください。しかし、「bmp_reader」と比較して「my_img」の有効期間を管理することが役立つと確信している場合は、次のようにします。

なぜ単に memory_reset を変更しないのですか。オブジェクト/関数がオブジェクトの「制御」を取得し、管理されたメモリで何かを行う場合、このポインタの値を別のものに割り当てる前に、メモリが解放されていることを確認する必要があります。以下をお勧めします。

void memory_reset(Image &img)
{
    delete[] img.mem; //add this line
    img.mem = new int [20*30];
}

また、同じ環境でマネージ/ガベージ コレクション/スマート ポインターを新規/削除メモリ管理タイプのスキームと混在させることは、一般的に不適切なプログラミング手法と見なされることに注意してください。

于 2013-05-23T17:29:05.790 に答える