web-dev-qa-db-ja.com

LocalAlloc Vs GlobalAlloc Vs malloc Vs new

私はさまざまなリンクでこれを検索しましたが、それでも疑念は残ります。

LocalAlloc vs GlobalAlloc vs malloc vs newのメモリ割り当ての違いがわかりません。

MSDNの次のリンクを確認しました。

メモリ割り当て方法の比較

次の文を説明してください:

malloc関数には、実行時に依存するという欠点があります。 new演算子には、コンパイラー依存および言語依存という欠点があります

26
User1234

Raymond ChenのOldNewThing からの抜粋

16ビットWindowsの時代に、違いは顕著でした。

16ビットWindowsでは、メモリは「セレクタ」と呼ばれる値を介してアクセスされ、それぞれが最大64Kをアドレス指定できました。 「データセレクター」と呼ばれるデフォルトセレクターがありました。いわゆる「ニアポインター」に対する操作は、データセレクターに関連して実行されました。たとえば、値が0x1234のニアポインターpがあり、データセレクターが0x012Fであった場合、* pを書き込んだとき、012F:1234でメモリにアクセスしていました。 (ポインターを宣言したとき、デフォルトでは近くにありました。遠いポインターが必要な場合は、明示的にFARと言う必要がありました。)

重要:ニアポインターは常にセレクター(通常はデータセレクター)に対して相対的です。

GlobalAlloc関数は、要求したメモリ量にアクセスするために使用できるセレクターを割り当てました。 「farポインター」を使用して、そのセレクターのメモリにアクセスできます。 「ファーポインター」は、セレクターとニアポインターを組み合わせたものです。 (近いポインターはセレクターに相対的であることに注意してください。近いポインターを適切なセレクターと組み合わせると、遠いポインターが得られます。)

プログラムのすべてのインスタンスとDLLは、HINSTANCEと呼ばれる独自のデータセレクターを取得しました。したがって、近いポインターpがあり、プログラム実行可能ファイルから* pを介してアクセスした場合、メモリにアクセスしましたプログラムインスタンスのHINSTANCEに関連するDLLからアクセスした場合、DLLのHINSTANCEに関連するメモリを取得しました。

したがって、16ビットWindowsでは、LocalAlloc関数とGlobalAlloc関数は完全に異なっていました。 LocalAllocは近いポインターを返しましたが、GlobalAllocはセレクターを返しました。

モジュール間で渡そうとするポインターは、「ファーポインター」の形式である必要がありました。これは、各モジュールには異なるデフォルトセレクターがあるためです。メモリの所有権を別のモジュールに移したい場合は、GlobalAllocを使用する必要がありました。これにより、受信者がGlobalFreeを呼び出してメモリを解放できるようになりました。

Win32でも、ローカルヒープとグローバルヒープを混同しないように注意する必要があります。一方から割り当てられたメモリを他方で解放することはできません。 Win32への移行により、ニアポインターとファーポインターに関する奇妙さはすべてなくなりました。ただし、ローカルヒープ関数とグローバルヒープ関数は、2つの異なるヒープインターフェイスです。

また、あなたが指定した link は、

32ビットWindowsから、GlobalAllocとLocalAllocは、プロセスのデフォルトヒープへのハンドルを使用してHeapAllocを呼び出すラッパー関数として実装されます。HeapAllocは、メモリを割り当てられなかった場合に例外を発生させるように指示できます。

mallocとnewの混乱については、Billy ONealの答えはそれをかなり明確に要約しています。

mallocとHeapAllocの違いについては、David Heffernan氏とLuis Miguel Huapaya氏の回答を組み合わせると、完璧なソリューションが得られます。

  • mallocは移植性があり、標準の一部です。 malloc(および他のCランタイムヒープ関数)はモジュールに依存します。つまり、1つのモジュール(DLL)のコードでmallocを呼び出す場合は、freeは移植性がなく、Windows API関数です。 HeapAllocの代わりにHeapAllocGetProcessHeap演算子をオーバーロードすることを含め、mallocの代わりにnewとともにdeleteを使用すると、動的に渡すことができます。モジュール間でオブジェクトを割り当て、メモリが1つのモジュールのコードで割り当てられ、メモリのブロックへのポインタが外部モジュールに渡されると別のモジュールのコードで解放される場合、メモリ破損を心配する必要はありません。
21
Abhineet

GlobalAllocLocalAllocは16ビット時代の古い関数です。 違いは、セグメントでのみ使用されるメモリ(使用されるメモリ)を割り当てなければならない場合があることでしたポインタ)、およびシステム上の他のプロセスやセグメントと共有するメモリを割り当てる必要がある場合がありました。今日、これらの人は何らかの形でHeapAllocなどのHeapXxx関数に転送します。新しいコードを作成していて、Cランタイムとのリンクを回避する必要がある場合は、代わりにHeapXxx関数を使用する必要があります。もちろん、これらのいずれかを呼び出した場合、プログラムはWindows上でのみコンパイルおよび実行されます。

mallocは「ランタイム依存」です。これを使用するには、Cランタイム(CRT)に対してリンクする必要があります。 CRTは、printfqsortなど、他のすべての標準Cライブラリ関数を含むライブラリです。これとリンクせずに、単純なWin32 APIプログラムを書くことができます(しかし、実際のソフトウェアでそれをしたい理由が正直にわかりません)。

newは、C++をコンパイルできるコンパイラを必要とするという点で、コンパイラ依存および言語依存です。 (そして通常newmallocの観点から実装されているので、おそらくCRTを使用する必要があります)

17
Billy ONeal