我刚接触Windows编程,我刚刚“浪费”了两个小时来寻找一个似乎每个人都知道的bug :你不能在DLL中的堆上创建一个对象,然后在另一个DLL (或主程序)中销毁它。
我几乎可以肯定在Linux/Unix上不是这样的(如果是这样,请说出来,但我非常确定我已经这样做了几千次,没有任何问题……)。
现在我有几个问题:
1)静态链接的DLL是否使用与主程序不同的堆?
2)静态链接的DLL是否映射在主程序的同一进程空间?(我非常确定这里的答案是肯定的,否则将指针从主程序中的函数传递到DLL中的函数是没有意义的)。
我说的是普通/常规DLL,而不是COM/ATL服务
编辑:所谓“静态链接”,我的意思是我不使用LoadLibrary来加载DLL,而是链接到存根库
发布于 2012-05-31 00:37:28
如果我有一个编译为.exe的应用程序,并且我想使用库,我可以从.lib文件静态链接库,也可以从.dll文件动态链接库。
每个链接的模块(即每个.exe或.dll)将链接到C或C++运行时的一个实现。运行时本身是一个库,它可以静态或动态地链接到不同的线程配置中。
说静态链接.dll,你是在描述这样一种设置吗?在这种设置中,应用程序.exe动态链接到库dlls,而库在内部静态链接到运行时?我会假设这就是你的意思。
同样值得注意的是,每个模块(.exe或.dll)都有自己的静态作用域,即.exe中的全局静态与.dll中同名的全局静态不是同一个实例。
因此,在一般情况下,不能假设在不同模块中运行的代码行使用运行时的相同实现,而且它们不会使用任何静态的相同实例。
因此,在处理跨越模块边界的对象或指针时,需要遵守某些规则。对于任何给定的地址,分配和释放必须在同一模块中进行。否则,堆将不匹配,也不会定义行为。
COM使用引用计数来解决这个问题,当引用计数达到零时,对象会自动删除。这是用于解决匹配位置问题的常见模式。
可能存在其他问题,例如窗口定义了某些操作,例如如何在每个线程的基础上而不是每个模块的基础上处理分配失败。这意味着,在模块B设置的线程上运行在模块A中的代码也可能遇到意外行为。
https://stackoverflow.com/questions/10820114
复制相似问题