9

DevStudio を使用して Windows で C/C++ アンマネージを使用して開発しています。

ヒープではなくスタックにメモリを割り当てたいのは、そのメモリを手動で解放する必要がないためです (スマート ポインターとそのすべてについて知っています。必要なメモリ割り当ての非常に特殊なケースがあります)。 A2W() および W2A() マクロの使用に似ています。

_allocaはそれを行いますが、非推奨です。代わりにmallocaを使用することをお勧めしますしかし、_malloca のドキュメントには、_malloca への呼び出しごとに ___freea への呼び出しが必須であると記載されています。_malloca を使用するという私の目的が無効になるため、代わりに malloc または new を使用します。

リークせずに _freea を呼び出さなくても済むかどうか、および内部にどのような影響があるかを誰かが知っていますか?

そうしないと、非推奨の _alloca 関数を使用することになります。

4

6 に答える 6

16

_malloca を呼び出すたびに _freea を呼び出すことが常に重要です。

_malloca は _alloca に似ていますが、保護のために追加のセキュリティ チェックと機能強化が追加されています。その結果、_malloca がスタックではなくヒープに割り当てられる可能性があります。これが発生し、_freea を呼び出さないと、メモリ リークが発生します。

デバッグ モードでは、_malloca は常にヒープに割り当てられるため、解放する必要があります。

しきい値がどのように機能するか、および _alloca の代わりに _malloca が存在する理由の詳細については、_ALLOCA_S_THRESHOLD を検索してください。


編集:

人がヒープに割り当てるだけで、スマートポインターなどを使用することを示唆するコメントがありました.

_malloca が提供するスタック割り当てには利点があるため、これを行う理由があります。_alloca も同じように機能しますが、スタック オーバーフローやその他の問題を引き起こす可能性が高く、残念ながら適切な例外を提供することはなく、むしろプロセスを破壊する傾向があります。_malloca はこの点ではるかに安全であり、ユーザーを保護しますが、_malloca がスタックではなくヒープに割り当てることを選択する可能性があるため (リリース モードではほとんどありません)、_freea を使用してメモリを解放する必要があるという代償があります。

メモリを解放する必要がないようにすることが唯一の目標である場合は、メンバーがスコープ外になったときにメモリの解放を処理するスマート ポインターを使用することをお勧めします。これにより、ヒープにメモリが割り当てられますが、安全であり、メモリを解放する必要がなくなります。ただし、これは C++ でのみ機能します。単純な古い C を使用している場合、このアプローチは機能しません。

他の理由でスタックに割り当てようとしている場合 (スタック割り当ては非常に高速であるため、通常はパフォーマンスのため)、_malloca を使用し、値に対して _freea を呼び出す必要があるという事実を受け入れることをお勧めします。

于 2009-04-09T16:06:13.267 に答える
3

考慮すべきもう 1 つのことは、割り当てを管理するために RAII クラスを使用することです。もちろん、これは、マクロ (またはその他のもの) を C++ に制限できる場合にのみ役立ちます。

パフォーマンス上の理由からヒープへのヒットを避けたい場合は、Matthew Wilson のauto_buffer<>テンプレート クラス ( http://www.stlsoft.org/doc-1.9/classstlsoft_1_1auto__buffer.html) で使用されている手法を参照してください。実行時のサイズ要求がコンパイラ時に指定されたサイズを超えない限り、これはスタックに割り当てられます。そのため、割り当ての大部分でヒープ割り当てなしの速度が得られますが (テンプレートのサイズを適切に設定した場合)、超過した場合でもすべてが正しく機能します。そのサイズ。

STLsoft には移植性の問題に対処するための多くの難点があるためauto_buffer<>、Wilson の著書「Imperfect C++」で説明されているより単純なバージョンを参照することをお勧めします。

組み込みプロジェクトでは非常に便利であることがわかりました。

于 2009-04-09T17:10:24.187 に答える
1

スタックにメモリを割り当てるには、適切な型とサイズの変数を宣言するだけです。

于 2009-04-09T16:01:19.317 に答える
1

以前にこれに答えましたが、デバッグモードでのみ機能することを意味する基本的なことを見逃していました。_malloca への呼び出しを、自動解放するクラスのコンストラクターに移動しました。

デバッグでは、常にヒープに割り当てられるため、これは問題ありません。ただし、リリースでは、スタックに割り当てられ、コンストラクターから戻ると、スタック ポインターがリセットされ、メモリが失われます。

私は戻って別のアプローチを取り、その結果、マクロ (eurgh) を使用してメモリを割り当て、そのメモリで _freea を自動的に呼び出すオブジェクトをインスタンス化しました。これはマクロなので、同じスタック フレームに割り当てられるため、実際にはリリース モードで動作します。私のクラスと同じくらい便利ですが、少し使いにくいです。

私は次のことをしました:

class EXPORT_LIB_CLASS CAutoMallocAFree
{
public:
    CAutoMallocAFree( void *pMem ) : m_pMem( pMem ) {}
    ~CAutoMallocAFree() { _freea( m_pMem ); }

private:
    void    *m_pMem;

    CAutoMallocAFree();
    CAutoMallocAFree( const CAutoMallocAFree &rhs );
    CAutoMallocAFree &operator=( const CAutoMallocAFree &rhs );
};

#define AUTO_MALLOCA( Var, Type, Length ) \
    Type* Var = (Type *)( _malloca( ( Length ) * sizeof ( Type ) ) ); \
    CAutoMallocAFree __MALLOCA_##Var( (void *) Var );

このようにして、次のマクロ呼び出しを使用して割り当てることができ、インスタンス化されたクラスがスコープ外になると解放されます。

            AUTO_MALLOCA( pBuffer, BYTE, Len );
            Ar.LoadRaw( pBuffer, Len );

明らかに間違ったことを投稿して申し訳ありません!

于 2013-08-22T10:54:37.127 に答える
0

あなたの懸念が一時メモリを解放しなければならないことであり、スマートポインタなどについてすべて知っている場合は、メモリが範囲外になったときにメモリが解放される同様のパターンを使用してみませんか?

template <class T>
class TempMem
{
  TempMem(size_t size)
  {
    mAddress = new T[size];
  }

  ~TempMem
  {
    delete [] mAddress;
  }

  T* mAddress;
}

void foo( void )
{
  TempMem<int> buffer(1024);

  // alternatively you could override the T* operator..
  some_memory_stuff(buffer.mAddress);

  // temp-mem auto-freed
}
于 2009-04-09T16:58:53.030 に答える