我在常规DLL中新建一个堆对象。我使用__declspec(dllexport)正确导出它,并使用__declspec(dllimport)链接将其导入EXE。只要我在DLL中正确定义了对象,但在EXE中执行/调试时,对象是未定义的。我错过了什么?名字错了吗?应该是extern" C" demangling帮助?
进一步说明: @Colin Robertson我的问题源于使用扩展DLL的原型,其代码在编译时与EXE集成。我知道我的应用程序需要直接从EXE中访问DLL中的对象,这在Windows扩展DLL中是可以的,因为代码集成。但是原型结果变成了内存,因为我的应用程序在执行期间创建了许多DLL,每个DLL都可以动态集成到运行的可执行文件中。因此,生产代码必须使用具有自动引用计数(dllmain等)的常规DLL,只要它不是静态链接的。这让我想到如何从EXE中访问DLL对象的当前问题?
因此,关于分配器通过的链接中的讨论是不相关的。第60点(60.避免在不同的模块中分配和释放内存。)在Sutter和Alexandrescu的书中不适用,因为EXE不负责对象的生命周期。此外,由于我使用共享库,以下情况属实:“具体来说,如果您使用Dll运行时选项,则单个dll - msvcrtxx.dll - 管理在所有dll之间共享的单个freestore,并且与该dll相关联的exe。“(请参阅StackOverflow的”谁将堆分配给我的DLL?“其线程被poke,Linus Kleen,mauris,Cody Gray,miku因某种原因关闭)。我的代码不会将DLL的分配/解除分配责任与EXE的使用请求混合在一起。
我认为问题在于,在常规DLL中,使用指向另一个模块中的对象的指针,在具有自己的消息泵的不同线程中运行的分配堆是灾难性的并且被编译器谴责。这是应该的。
但我的问题仍然合法。
我看到Windows解决这种情况的两种方式。一个是Send / PostMessage调用,它在其他线程队列上发布消息,另一个是COM编组。对于前者,我会遇到返回值的问题。由于我所做的基本上是一个远程过程调用,我的EXE希望从DLL返回结果,而SendMessage只返回一个HRESULT。至于后者,这正是COM在公寓线程应用程序中编组指针时所做的事情(参见MSDN中的“单线程公寓”)。 COM旨在让您在线程甚至进程之间传递指针。可能有第三种C ++方式使用Pimpl习语(参见http://www.c2.com/cgi/wiki?PimplIdiom),但这种方法工作量大,有缺点。感谢MVP Scott McPhillips提出这个建议。
有没有人有关于采用哪种方式的建议或经验?
答案 0 :(得分:-1)
不要那样做。这是Sutter和Alexandrescu的C++ Coding Standards书中的第60项,我强烈推荐这本书。单独的模块可以使用它们自己的运行时库版本,包括基本分配例程。在一个模块的堆上分配的东西可能无法从另一个模块访问,或者具有用于分配和释放它们的不同约定。名称修改惯例可能会有所不同,但这是您最不担心的问题。这是另一个StackOverflow问题,它提供了更详细的答案,说明为什么这是一个坏主意,以及该做什么:Is it bad practice to allocate memory in a DLL and give a pointer to it to a client app?