有关DLL中New和外部Delete的若干问题

xiaolizi 2003-12-16 08:15:36
大家好,

碰到一个问题,说出来大家讨论讨论。

我们需要在Dll中new一个class或者struct的实例,通过接口把这个实例传给了主程序(调用dll的程序),最后这个实例的释放(delete)是由主程序来执行的,这时我们的问题出现了,vs.net抛出一个debug模式下的异常,是在delete函数中。后来我试了另外一种情况,即在主程序中new的实例在dll中delete也会有相同的问题。哪位大侠知道为什么?


另外,还有一个小问题,就是在dll中的导出(dllexport)类中,如果有stl的变量存在如list<int>等,在编译的时候会有一个有关dll 接口不一致的warning,不知道怎么解决这个问题。

...全文
246 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
widewave 2003-12-18
  • 打赏
  • 举报
回复
mark
xiaolizi 2003-12-18
  • 打赏
  • 举报
回复
To plainsong(短歌)

有关将一些常用的基本类做成静态库也是有个问题,如果一个工程中有两个独立的模块做成了Dll,这两个Dll中同时用到了这些基本类或者函数,这钟情况下两个Dll中有了两分用到的基本类的copy,另外修改了静态库的实现而没有修改接口,这两个独立的dll还需要重新编译等等一些问题。如果这些基本类也是dll封装是不是更好呢?所以不知道调用一个dll中的函数和调用一个本地模块中的函数在效率上有什么差别?
xiaolizi 2003-12-17
  • 打赏
  • 举报
回复
To wind2006()
sorry,对iso的东东不熟悉。^_^
xiaolizi 2003-12-17
  • 打赏
  • 举报
回复
To plainsong(短歌)

DLL调用本身 会有多大代价呢,这个可否详细介绍一下?

^_^
tigerfox 2003-12-17
  • 打赏
  • 举报
回复
为什么不写成COM形式!
wind2006 2003-12-17
  • 打赏
  • 举报
回复
两位哥哥帮我看看 wind2006 发的一个小问题的帖子好么
小弟明天要交作业了啊
谢谢你们,在百忙之中!
短歌如风 2003-12-17
  • 打赏
  • 举报
回复

我觉得Dll不应该作为简单的代码重用手段,而应该作为逻辑重用手段。也就是说,用一个DLL维护一组相关的逻辑。事实上,与其说它是代码重用手段,还不如说是代码组织手段更合适。

象vector、matrix等这些只是用来封装类似于“基本数据类型扩展”的类的代码,不应该用DLL去重用,而应该是以源代码或是静态库方式重用。此外,如果你要重用的是模板,那么就只有源代码一种重用方法了,因为模板只有实例化之后才能产生可以加入到静态库或DLL中去的代码。

当你使用DLL调用进行重用时,你就不要去考虑多态的代价了,因为DLL调用本身就已经有代价了。
xiaolizi 2003-12-17
  • 打赏
  • 举报
回复
To plainsong(短歌)

有点抽象,大致明白了上面的解说。

因为我现在存在这样一种困惑,一般我们都会有一些平常比较常用的fucntion,class,这些都会代码都会跨项目的被使用到,所以我把这些代码做成dll,方便以后的需要。基于这样一个目的,我们去构架这个dll,会发现其中有很多简单明了的类,比如一个CVector3f,一个CMatrix44,或者一个类似std::string这样的类,那么这些类的导出该以怎样一种规则来制定呢?

^_^
短歌如风 2003-12-17
  • 打赏
  • 举报
回复
这里面有一个模块划分的问题。对于需要跨模块调用的功能,最好是分处于不同层次的代码,相互之间不要有很多共用的对象。有时不同层次有相似的对象,但它们只是相似而已,并不是同一类型的对象,因为它们处于不同层次。而对于某一独立模块,引出的对象类型应该很少,用Facade模式封装起来是个不错的主意。

C++中的类要分成两种,一种是对基本数据类型的扩展,比如大家经常用到的std::string等,特点是值语义、无多态操作等,这种类没有必要跨模块共享;另一种是逻辑对象的分类,它们是否要共享要根据对象的职责来确定,有些是模块内部使用的,有些则是负责与其它模板交互的,只有后者才是应该共享的。

此外,共享使用的对象内部使用的对象是不需要这个接口的——如果在模块内部它本身就不需要的话。
xiaolizi 2003-12-17
  • 打赏
  • 举报
回复
To plainsong(短歌)

理解了你的回复,这正是我想要的,谢谢。^_^
这边还有一个小问题,如果为每一个导出的class都做一个wrap,如果导出的类很多不是开销很大?如果有些类是比较简单的,这样也需要为每个类做一个接口吗?
短歌如风 2003-12-16
  • 打赏
  • 举报
回复

不同的DLL中完全可能会维护不同的局部堆,这与编译器的实现有关。有些编译器可以选择使用进程共享的局部堆,但性能会受影响。

如果是不同的局部堆,当你在DLL中new时,是在DLL的堆中分配的;而当你在EXE中delete时,EXE会认为它是在EXE的局部堆中分配的,从而用EXE的堆信息去释放它,从而可能导致错误。具体情况与堆管理代码的实现有关。

最好为你的class或struct提供一个虚的free方法,在里面调用delete。不管是从EXE中分配的还是从DLL中分配的,都可以安全地用free方法释放,因为free是虚的,它的代码会和分配它的代码编译在同一个可执行体中。

我不赞成用引出类的方法提供功能,因为类成员的签名生成并没有一个标准,很难使用。

用DLL提供的类最好是只引出创建对象的函数,返回类型是一个“纯抽象类”指针,我说的“纯抽象类”指没有成员变量,没有非抽象方法的类。并且有一个公开的抽象的free方法负责释放。使用时调用创建函数创建一个(衍生类) 的对象并返回,然后调用对象的成员方法来完成操作。

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧