跨dll边界的内存分配和释放
我知道在一个 dll 中进行的内存分配然后在另一个 dll 中释放会导致各种问题,尤其是关于 CRT.在导出 STL 容器时,这类问题尤其成问题.我们以前遇到过这类问题(在编写与我们的库链接的自定义 Adob??e 插件时),我们已经通过定义我们在所有容器中使用的自己的分配器来解决这些问题,例如:
I understand that memory allocations made in one dll then subsequently free'd in another can cause all sort of problems, especially regarding the CRT. These sorts of problems are especially problematic when it comes to exporting STL containers. We've experienced these sorts of problems before (when writing custom Adobe plugins that linked with our libraries) and we've worked round these issues by defining our own allocator that we use in all our containers, eg:
typedef std::vector < SessionFields,
OurAllocator < SessionFields > >
VectorSessionFields;
typedef std::set < SessionFields,
std::less < SessionFields >,
OurAllocator < SessionFields > >
SetSessionFields;
这在向/从我们的代码传递类型时效果很好,但是我们遇到了一个问题,因为我们现在必须调用 Adob??e SDK 中的一个函数,该函数返回一个填充的向量,当它消失时会导致崩溃范围.
This has worked well when passing types to/from our code, however we've hit a problem in that we're now having to call a function in Adobe's SDK that returns a populated vector which causes a crash when it goes out of scope.
显然,当它最终在我的代码中被释放时,内存被分配到属于不同堆的 Adob??e SDK 中是一个问题.所以我想也许我可以做一些聪明的事情,比如以某种方式覆盖或导出他们 SDK 中使用的分配器,这样我就可以用它来清理从他们的函数返回的容器.
Obviously, it's a problem with memory being allocated in Adobe's SDK belonging to a different heap when it's finally free'd in my code. So I'm thinking that maybe I could do something clever like somehow overriding or exporting the allocator used in their SDK so I could use it to clean up containers returned from their functions.
我也在考虑编写一个包装器或某种类型的 thunking 层,以便在我的代码和 SDK 之间安全地编组 STL 容器(虽然这听起来很混乱).
I'm also looking at writing a wrapper or some sort of thunking layer whereby STL containers would be safely marshalled between my code and the SDK (although this does sound very messy).
或者,我也在考虑使用 GetProcessHeaps
来识别 SDK 中使用的堆,并尝试针对此堆而不是默认堆进行释放.
Alternatively, I'm also looking at using GetProcessHeaps
to identify the heap used from within the SDK, and try to free against this heap, instead of the default heap.
有人对我们如何解决这个问题有任何建议吗?
Has anyone any advice on how we can solve this problem?
推荐答案
具有讽刺意味的是,Adobe 源库有一个 adobe::capture_allocator
类专门针对此类 DLL 安全性编写.它的工作方式是在它被实例化时捕获本地 new
和 delete
,并在对象的生命周期内携带它们.(有关如何执行此操作的详细信息,请参阅 adobe::new_delete_t
,尤其是此处的实现.)使用捕获的delete<进行释放/code> 例程,保证无论您身在何处都可以使用正确的
delete
进行删除.
Ironically enough, the Adobe Source Libraries has a adobe::capture_allocator
class that was written specifically with this kind of DLL safety in mind. The way it works is to capture the local new
and delete
at this point it is instantiated, and to carry them both around for the lifetime of the object. (See adobe::new_delete_t
for details on how it does this, especially the implementation here.) Deallocations take place with the captured delete
routine, guaranteeing that no matter where you are you are deleting with the proper delete
.
您可以看到在整个 version_1
中使用的 capture_allocator
> Adob??e 源库中的类型,例如 adobe::any_regular_t
和 adobe::copy_on_write
.capture_allocator
也应该与所有 STL 容器类型兼容.
You can see capture_allocator
used throughout the version_1
types in the Adobe Source Libraries, such as adobe::any_regular_t
and adobe::copy_on_write
. capture_allocator
should be compatible with all STL container types as well.
更新:capture_allocator
不符合标准,因为它保留了状态.这不应成为其可用性的大障碍,但这确实意味着不能保证其使用符合标准的容器.
Update: capture_allocator
is not standard-compliant because it retains state. This should not be a big hindrance to its usability, but it does mean its use is not guaranteed to work with standard-compliant containers.
相关文章