主程序调用DLL接口函数时内存分配/释放出了点问题

two_ears 2008-04-08 09:08:59
准备用DLL的形式来模块化各个功能点,
使用标准库的容器类模板来管理数据,
在定义DLL接口函数的时候,用了string的引用作为参数。如下所示。

DLL接口函数:
void Get(string &strBuf)
{
strBuf="abc";
}

宿主进程调用如下:
{
...
string str;
Get(str);
...
}
结果到了这里,str析构时就会出现异常。
我想可能是我对string的理解有些问题。

此后,我以为是string在释放内存造成的,于是又做了一些尝试,
1.在Get函数中用new分配内存,由调用者释放,也会出现同样的异常。
2.如果Get不是在DLL中实现,和调用过程放在一个映象文件中,这两种分配方式都不会有问题。
3.只要我调用DLL中的过程,但不释放其中分配的内存,就一切正常。(允许修改)

这让我不太明白,DLL中的过程应该和调用者在一个进程,内存空间应该是共享的,
难不成DLL中返回的堆地址对于主调过程有歧义造成释放时异常?

不知道是不是把问题说清楚了,请高手指教。谢谢!
...全文
832 35 打赏 收藏 转发到动态 举报
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
two_ears 2008-04-11
  • 打赏
  • 举报
回复
怎么都说到class复用上了,呵呵
COM不是class复用吧,用C同样可以做COM呀
唉,跑题了,不提了
two_ears 2008-04-11
  • 打赏
  • 举报
回复
这个动态库不用为不同语言调用做准备
只是为了方便才用了一下stl,其实接口中并没有这个必要
COM号称提供一个二进制级别的标准,做到语言无关
看过COM技术内幕,其实巧归巧,但说到底也没有什么神奇的
而且这个帖子可能是我说多了,总是把问题扯到无关的事情上
其实,就是内存分配/释放出错的问题
刚才刚刚试了一下HeapAlloc/HeapFree,问题就不存在了
就是不太明白MFC的库怎么会引起这么多问题,因为调用相关的代码好像和MFC也没有关系呀
也许真像cbg7997说的,是new/delete的实现的问题,这就不明白了
也许是想的有点多了吧
  • 打赏
  • 举报
回复
归根结底是 string&参数类型惹得祸
不同版本的扩展dll是不通用的,每个版本的对同样的class处理可能都不一样的.

再说了,这样的dll能被C,delphi,VB,BCB使用么? 但API都能.就是因为API是标准DLL,所以通用.

要真想class复用,就封装成COM.要么就按照C的标准来,不要用任何class的东西.
browningblue 2008-04-10
  • 打赏
  • 举报
回复
I agree r_swordsman.
two_ears 2008-04-10
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 cbg7997 的回复:]
关键看string内部怎么分配的对象。我跟了一下,最后调用的是operator new(用windows API函数virtualAlloc实现)。
我做了个小实验,在dll中new对象,在exe中delete,出错。
但是用GlobalAlloc和GlobalFree就没问题。这就证明进程空间对exe还是dll都是共用的,问题应该出在new和delete的实现上。具体还不是很清楚,请高手解答。
[/Quote]

哦,这个倒没试过,等明天试一下,谢啦。
two_ears 2008-04-10
  • 打赏
  • 举报
回复
to r_swordsman:昨天刚刚又做过尝试,mfc选择shared dll,就不会有问题。只要有一个选择static就不行。你可以试试。如果生成dll环境使用vc2005,怎么都不行,都用2005都用shared又没有问题了。static总有问题。这个问题还是弄不明白。

对了,前面帖子里说的有点问题,并不是异常,而是一个断言,那天调试的时候没有注意。
至于multithread,本来就是用的这个选项,呵呵。没用。
wjlsmail 2008-04-10
  • 打赏
  • 举报
回复
使用标准DLL,接口以char *为参数。
Exe提供 char *并分配、释放空间。
DRACULAX05 2008-04-10
  • 打赏
  • 举报
回复
讨论这个问题没有必要,只要把DLL和EXE的Code Generation都改成 Debug Multithreaded Dll就好了,编译器会帮你搞定一切
wbczyh 2008-04-10
  • 打赏
  • 举报
回复
学习了...
KUCHIBUE 2008-04-09
  • 打赏
  • 举报
回复
就是会出错的,我用的时候也一样。只要涉及到new和delete。
xzgyb 2008-04-09
  • 打赏
  • 举报
回复
如果没记错的话,
编译是没错的
exe和dll工程中
Project/Settings中C++/Code Generation
Use run-time library选Debug Multithreaded Dll就可.
Release选 Multithreaded Dll,

注意一定要exe和dll工程两个都要设置.

r_swordsman 2008-04-09
  • 打赏
  • 举报
回复
奇怪...你们都出错了..怎么我的没出错?

dll

#include "stdafx.h"
#include <string>



BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}


extern "C" __declspec(dllexport) void getstring(std::string& s)
{
s = "abcdefg";
}



exe


#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
#pragma comment(lib, "..\\debug\\stringdlla.lib")

extern "C" __declspec(dllimport) void getstring(std::string& s);
typedef void (*pf)(std::string&);
char *p1 = "hello world!";

void test(string& str);
pf f;
int main()
{
#ifdef DUBUG
HINSTANCE h =LoadLibrary(L"..\\debug\\stringdlla.dll");
#else
HINSTANCE h =LoadLibrary(L"stringdlla.dll");
#endif
f = (pf)GetProcAddress( h, "getstring");

string st;
test(st);
cout << st;
getstring(st);
cout << st;
f(st);
cout << st;

return 0;
}

void test(string& str)
{
str = p1;
}


cbg7997 2008-04-08
  • 打赏
  • 举报
回复
关键看string内部怎么分配的对象。我跟了一下,最后调用的是operator new(用windows API函数virtualAlloc实现)。
我做了个小实验,在dll中new对象,在exe中delete,出错。
但是用GlobalAlloc和GlobalFree就没问题。这就证明进程空间对exe还是dll都是共用的,问题应该出在new和delete的实现上。具体还不是很清楚,请高手解答。
two_ears 2008-04-08
  • 打赏
  • 举报
回复
哦,错了错了,分没有给错,是看聊天记录看错了,该谢的没写错,我这人糊里糊涂的,见笑了。
two_ears 2008-04-08
  • 打赏
  • 举报
回复
哦,帮我谢谢他,分都给了,下回吧
  • 打赏
  • 举报
回复
抢沙发的那个
two_ears 2008-04-08
  • 打赏
  • 举报
回复
我看了半天的,就是你贴的那个聊天记录,早知道你后面有总结,就不费劲了。
哦,错了,是该问,过儿是谁。
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 two_ears 的回复:]
to akirya:谢了,这个比较有价值,呵呵,这个坏,是什么人?
给分了。
很久很久没到CSDN来了。以前还来过的,其实再忙也应该来学习学习。呵呵。
[/Quote]

刚才跟过儿的聊天记录,都贴出来了,你没看.
two_ears 2008-04-08
  • 打赏
  • 举报
回复
to akirya:谢了,这个比较有价值,呵呵,这个坏,是什么人?
给分了。
很久很久没到CSDN来了。以前还来过的,其实再忙也应该来学习学习。呵呵。
  • 打赏
  • 举报
回复
string在dll和exe中有两份实现,这个对吧
那么他们的alloc也就是有两份了
那就是说alloc中的 内存分配链表就有两份了
string在dll中分配内存了,那么就是说,是使用dll中的alloc分配内存了,可以得出 这个内存是登记dll中的内存池中了.
在exe中释放,的话........修改了不属于exe的内存池
加载更多回复(15)

64,637

社区成员

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

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