我是Windows编程的新手,我只是迷失了两个小时来寻找每个人似乎都知道的错误:您不能在DLL的堆上创建对象,而在另一个DLL(或主程序)中销毁它。
我几乎可以肯定,在Linux / Unix上不是这种情况(如果可以,请说出来,但是我敢肯定,我做了数千次都没有问题……)。
在这一点上,我有两个问题:
1)静态链接的DLL是否使用与主程序不同的堆?
2)静态链接的DLL是否映射在主程序的相同进程空间中?(我非常确定,这里的答案是肯定的,否则将指针从主程序中的函数传递到DLL中的函数就没有意义了)。
我说的是普通/常规DLL,而不是COM / ATL服务
编辑:通过“静态链接”我的意思是我不使用LoadLibrary加载DLL,但我与存根库链接
DLL / exes将需要链接到C运行时库的实现。
对于C Windows运行时库,如果希望链接到以下内容,则可以选择指定:
它们中的每一个都将引用一个不同的堆,因此不允许您从一个运行时库的堆获得的地址传递给另一个。
现在,它取决于您所讨论的DLL已链接到哪个C运行时库。假设,您正在使用的DLL已链接到静态C运行时库,而您的应用程序代码(包含主函数)已链接到多线程C运行时DLL,那么如果您将指针传递给在DLL到您的主程序,然后尝试将其释放,反之亦然,这可能导致未定义的行为。因此,根本原因是C运行时库。请仔细选择它们。
请在此处和此处找到有关支持的C运行时库的更多信息
来自MSDN的报价:
注意 请勿混合使用静态版本和动态版本的运行时库。 进程中有多个运行时库副本可能会导致问题,因为一个副本中的静态数据不会与另一副本共享。链接器可防止您同时链接一个.exe文件中的静态版本和动态版本,但最终仍可以得到两个(或更多)运行时库副本。例如,与运行时库的动态(DLL)版本链接的.exe文件一起使用时,与运行时库的静态(非DLL)版本链接的动态链接库可能会导致问题。 。(您还应避免在一个过程中混合使用库的调试版本和非调试版本。)