主题:调用DLL中的API时,传递给它的参数为什么一定要堆上的?
调用DLL中的API时,传递给它的参数为什么一定要堆上的?
近来一直忙于编写短信服务程序,
前阵子由于开展一个大活动,大量短信涌进来,
多的时候一秒钟8条,
但是我给他们发送回复却达不到这样的速度(移动网关限速),
于是大量待发短信积压在内存中,导致两个问题:
一是内存使用爆涨,
二是这个服务程序不能退出(因为待发短信没发完)。
那个活动是下午五点钟结束的,但是待发短信却到七点才发完。
于是我给程序做了改变,将立即发送回复改为写入数据库,
然后从数据库里一次提取几条短信发送,
这样不会积压在内存里,而且随时可以退出服务。
下次启动服务可以继续发送。
由于不再积压于内存,
我想就不用new内存来存放了吧,我就用用栈上的内存算了,
于是做了这样的改动:
以前是这样的:
CMt *pMt = new CMt(...);//堆上申请实例
PostThreadMessage(....,(LPARAM)pMt);//将要发送的内容通知负责发送的线程
CMt *pMt = (CMt*)lParam;//负责发送的线程拿到了消息
pMt->Submit();//Submit是成员函数,里面调用了DLL中的API
delete pMt;
现在是这样做的:
线程之间根本不用消息通信,直接写入数据库,
发送线程从数据库里读到一个记录
既然不用存在内存里,就不用new内存了,直接用栈吧。
CMt mt;//栈内开劈实例
......//将数据库的内容填入mt
mt.Submit();//调用API时出错
百思不得其解,
想来想去,这次的改变主要在于用数据库代替了消息,
但是这个与调用DLL中的API无关啊。
那只有内存了。
以前的做法传递给API的参数是堆内存中的,
现在的做法传递给API的参数是栈内存中的,
于是我试了一下,仍旧在堆上申请实例,
这下居然成功了,调用API不出错了。
那么,调用API时,传递给它的参数为什么一定要堆上的?
顺便说一下:
我是在Visual Studio .NET 2002 DEBUG下编译的。
对于VC,我觉得有许多不可思议之处:
下面提两点:
以前我用的是隐式链接,编译连接的时候就把DLL里的函数连进来了,
这样的程序运行了一年多的时间,没有任何问题
后来改成显式连接,但是冒出了一个问题:
CMt *pMt;
....
pMt->Submit();
delete pMt;//出错,该实例无法删除。
我改为RELEASE编译,就正常了。
这个问题在VC++6中出现的,.Net没有出现。
现在又做了个改动,改成使用栈内存,
结果调用DLL里的函数出错,
不得不又改为使用堆内存。
那么,这两个情况放一起,总结一下:
一、必须用new来申请堆内存,否则用栈内存就无法传递到API中,
二、必须用RELEASE,否则就无法delete。(对于VC++6)
近来一直忙于编写短信服务程序,
前阵子由于开展一个大活动,大量短信涌进来,
多的时候一秒钟8条,
但是我给他们发送回复却达不到这样的速度(移动网关限速),
于是大量待发短信积压在内存中,导致两个问题:
一是内存使用爆涨,
二是这个服务程序不能退出(因为待发短信没发完)。
那个活动是下午五点钟结束的,但是待发短信却到七点才发完。
于是我给程序做了改变,将立即发送回复改为写入数据库,
然后从数据库里一次提取几条短信发送,
这样不会积压在内存里,而且随时可以退出服务。
下次启动服务可以继续发送。
由于不再积压于内存,
我想就不用new内存来存放了吧,我就用用栈上的内存算了,
于是做了这样的改动:
以前是这样的:
CMt *pMt = new CMt(...);//堆上申请实例
PostThreadMessage(....,(LPARAM)pMt);//将要发送的内容通知负责发送的线程
CMt *pMt = (CMt*)lParam;//负责发送的线程拿到了消息
pMt->Submit();//Submit是成员函数,里面调用了DLL中的API
delete pMt;
现在是这样做的:
线程之间根本不用消息通信,直接写入数据库,
发送线程从数据库里读到一个记录
既然不用存在内存里,就不用new内存了,直接用栈吧。
CMt mt;//栈内开劈实例
......//将数据库的内容填入mt
mt.Submit();//调用API时出错
百思不得其解,
想来想去,这次的改变主要在于用数据库代替了消息,
但是这个与调用DLL中的API无关啊。
那只有内存了。
以前的做法传递给API的参数是堆内存中的,
现在的做法传递给API的参数是栈内存中的,
于是我试了一下,仍旧在堆上申请实例,
这下居然成功了,调用API不出错了。
那么,调用API时,传递给它的参数为什么一定要堆上的?
顺便说一下:
我是在Visual Studio .NET 2002 DEBUG下编译的。
对于VC,我觉得有许多不可思议之处:
下面提两点:
以前我用的是隐式链接,编译连接的时候就把DLL里的函数连进来了,
这样的程序运行了一年多的时间,没有任何问题
后来改成显式连接,但是冒出了一个问题:
CMt *pMt;
....
pMt->Submit();
delete pMt;//出错,该实例无法删除。
我改为RELEASE编译,就正常了。
这个问题在VC++6中出现的,.Net没有出现。
现在又做了个改动,改成使用栈内存,
结果调用DLL里的函数出错,
不得不又改为使用堆内存。
那么,这两个情况放一起,总结一下:
一、必须用new来申请堆内存,否则用栈内存就无法传递到API中,
二、必须用RELEASE,否则就无法delete。(对于VC++6)