何が起こるかは基本的にこれです。個別にコンパイルされたすべてのコード (DLL または EXE) には、メモリ マネージャーと呼ばれる、システムからメモリを割り当てて管理する独自のコードが含まれています。簡単に言えば、そのコードが初期化されると、システムから大きなメモリ ブロックが割り当てられます。その後、GetMem を実行したり、文字列や配列などを割り当てたりするときに、メモリ マネージャーはその大きなブロックの一部を使用済みとしてマークします。それらを FreeMem/deallocate すると、それらは未使用としてマークされます。
ここで、EXE と DLL があり、どちらも独自のメモリ マネージャーを持っているとします。EXE は DLL プロシージャを呼び出し、DLL は文字列 (PChar) を割り当て、グランド メモリ ブロックの一部を使用済みとしてマークします。次に、ポインターを EXE に返します。EXE はそれを使用し、後で解放することを決定します。EXE はそれ自身のメモリ マネージャへのポインタを与え、それを解放するように要求しますが、それは EXE のグランド メモリ ブロックからでもありません! EXE のメモリ マネージャは、他のユーザーのメモリを「解放」する方法を知りません。
そのため、DllReleaseString() を呼び出して、借用したメモリ ポインタを DLL に返し、DLL 自身の内部メモリ マネージャがそれを解放できるようにする必要があります。
ここで、共有メモリ マネージャーが行うことは、相互に接続することです。DLL 内のメモリ マネージャーと EXE 内のメモリ マネージャーは互いに通信する方法を知っており、DLL のメモリ ポインターを EXE のメモリ マネージャーに渡すと、それが DLL からのものであることを認識し、DLL メモリ マネージャーに解放させます。もちろん、これは DLL と EXE メモリ マネージャの両方が同じメモリ マネージャ コードから構築されている場合にのみ可能です (そうでなければ、お互いを認識できません!)。DLL メモリ マネージャが共有メモリ マネージャで、EXE メモリ マネージャが別のものである場合、DLL メモリ マネージャは EXE にメモリの解放を「要求」できず、EXE メモリ マネージャは試行さえしません (共有ではありません)。
したがって、DLL をユニバーサルにしたい場合は、メモリ マネージャーが相互に通信することに依存することはできません。DLL は、別のメモリ マネージャーに依存する EXE または DLL と共に使用される可能性があり、まったく別の言語で記述されている可能性があります。プロジェクトのすべての部分を制御し、どこでも同じマネージャーを明示的に設定できる場合にのみ、メモリ マネージャーを共有できます。