关于进程中同时动态加载同一DLL问题

rundll64 2014-04-20 09:45:35
问题描述:
一个基于Dlg对话框的工程,在工程中设定了时间控件。通过参数,在不同的时间段内调用同一个DLL返回相应的结果

由于时间段有重复,例如张三,李四都在10:00执行,间隔10分钟一次

问题就出现了,会有一次动态加载的DLL没有产生返回值。


CString str;
HINSTANCE hInst;
hInst=LoadLibrary(_T("te.dll"));
typedef CString (_stdcall *mGg)(CString W, CString R, int i,int iW);
mGg G=(mGg)GetProcAddress(hInst,"G");
if(!G)
{
AfxMessageBox(_T("sru-获取函数地址失败!"));
return;
}
str = G(strU,strR,iT,iW);
。。。。。。。。
FreeLibrary(hInst);


...全文
720 21 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
Eleven 2014-04-23
  • 打赏
  • 举报
回复
只加载一次,卸载一次,程序运行期间一直使用即可。
zcchm 2014-04-23
  • 打赏
  • 举报
回复
引用 16 楼 rundll64 的回复:
[quote=引用 15 楼 zcchm 的回复:] 1 改成静态隐式加载,或者程序开始时加载,退出时卸载; 2 解决内存泄露问题,可以使用debug版本程序或者使用DebugDiag工具; 即使你频繁load/free,失败的时候可以GetLastError看一下错误信息是什么。
隐式连接的时候如果是10分钟跑着是没有问题的。但是如果更新时间小于5分钟的话,就出问题了 Load/Free的话就没这个问题[/quote] 不是没有问题,而是问题没有暴露出来而已。 你应该首先解决隐式加载爆出来的问题。
rundll64 2014-04-23
  • 打赏
  • 举报
回复
引用 15 楼 zcchm 的回复:
1 改成静态隐式加载,或者程序开始时加载,退出时卸载; 2 解决内存泄露问题,可以使用debug版本程序或者使用DebugDiag工具; 即使你频繁load/free,失败的时候可以GetLastError看一下错误信息是什么。
隐式连接的时候如果是10分钟跑着是没有问题的。但是如果更新时间小于5分钟的话,就出问题了 Load/Free的话就没这个问题
rundll64 2014-04-23
  • 打赏
  • 举报
回复
引用 20 楼 zcchm 的回复:
解决内存泄露问题,一种是根据你上面的dumping信息。 比如:Data: <<!DOCTYPE html P> 3C 21 44 4F 43 54 59 50 45 20 68 74 6D 6C 20 50 显然是返回的http response信息的一部分,需要你自己结合代码去分析。 另一种方法借助DebugDiag之类的工具。 既然选择C++,就要研究如何解决这些内存问题,否则,不如选择C#。 从另外一个角度来讲,可以研究一下boost中(已经纳入C++11标准)unique_ptr/shared_ptr/weak_ptr等智能指针管理堆内存。
很全面。我一会去试试
zcchm 2014-04-23
  • 打赏
  • 举报
回复
解决内存泄露问题,一种是根据你上面的dumping信息。 比如:Data: <<!DOCTYPE html P> 3C 21 44 4F 43 54 59 50 45 20 68 74 6D 6C 20 50 显然是返回的http response信息的一部分,需要你自己结合代码去分析。 另一种方法借助DebugDiag之类的工具。 既然选择C++,就要研究如何解决这些内存问题,否则,不如选择C#。 从另外一个角度来讲,可以研究一下boost中(已经纳入C++11标准)unique_ptr/shared_ptr/weak_ptr等智能指针管理堆内存。
rundll64 2014-04-23
  • 打赏
  • 举报
回复
[quote 不是没有问题,而是问题没有暴露出来而已。 你应该首先解决隐式加载爆出来的问题。[/quote] 我的那个DLL主要就是读取网页内容,然后正则我需要的信息更新到我自己的数据库里。 这几天经过反复的测试,发现在获取完网页内容后,在退出函数时就存在内存泄漏的问题。但是仔细观察过每一个过程,没有发现问题到底产生在什么地方。

Detected memory leaks!
Dumping objects ->
{14134} normal block at 0x05E223D8, 43 bytes long.
 Data: <http://baidu.lec> 68 74 74 70 3A 2F 2F 62 61 69 64 75 2E 6C 65 63 
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\inet.cpp(878) : {1097} normal block at 0x02F6E920, 4096 bytes long.
 Data: <<!DOCTYPE html P> 3C 21 44 4F 43 54 59 50 45 20 68 74 6D 6C 20 50 
{1096} normal block at 0x02F6CD98, 24 bytes long.
 Data: <  p             > 1C 00 70 01 03 00 00 00 03 00 00 00 01 00 00 00 
{1095} normal block at 0x02F6CD20, 58 bytes long.
 Data: <  p             > 1C 00 70 01 14 00 00 00 14 00 00 00 01 00 00 00 
{1094} normal block at 0x02F6E4F0, 48 bytes long.
 Data: <  p             > 1C 00 70 01 0F 00 00 00 0F 00 00 00 01 00 00 00 
{1093} normal block at 0x02F6CCA8, 58 bytes long.
 Data: <  p             > 1C 00 70 01 14 00 00 00 14 00 00 00 01 00 00 00 
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\inet.cpp(610) : {1092} client block at 0x02F6E688, subtype c0, 76 bytes long.
a CHttpFile object at $02F6E688, 76 bytes long
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\plex.cpp(29) : {1089} normal block at 0x02F6CBF0, 124 bytes long.
 Data: <                > 00 00 00 00 0C CC F6 02 04 00 CC 00 0C D2 1F 00 
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\map_pp.cpp(69) : {1088} normal block at 0x02F6E608, 68 bytes long.
 Data: <                > 00 CC F6 02 00 00 00 00 00 00 00 00 00 00 00 00 
Object dump complete.

这个就是正常执行了函数后的泄漏信息。查阅资料无果。
zcchm 2014-04-22
  • 打赏
  • 举报
回复
1 改成静态隐式加载,或者程序开始时加载,退出时卸载; 2 解决内存泄露问题,可以使用debug版本程序或者使用DebugDiag工具; 即使你频繁load/free,失败的时候可以GetLastError看一下错误信息是什么。
zcchm 2014-04-22
  • 打赏
  • 举报
回复
隐式加载有什么问题?为什么要频繁的Load/Free?
rundll64 2014-04-22
  • 打赏
  • 举报
回复
引用 12 楼 hushoubo 的回复:
[quote=引用 11 楼 WUYUAN2011WOAINI 的回复:] [quote=引用 10 楼 rundll64 的回复:] [quote=引用 9 楼 zzdmfk 的回复:] [quote=引用 7 楼 rundll64 的回复:] [quote=引用 6 楼 zzdmfk 的回复:] 最好不要重复这样做。可以程序运行即loadlibrary,结束时freelibrary. 不然同步起来。
我也在考虑这个问题,不过不会这么弄,能给段demo看看吗? [/quote] 这两个做全局变量或没访问限制的变量: HINSTANCE hInst; mGg G=(mGg)GetProcAddress(hInst,"G"); 对话框的oninitdialog()里: hinst=loadlibrary......; G=(mGg)GetProcAddress(hInst,"G"); 对话框类的onclose里面: freelibrary; [/quote] 嗯嗯,我也是这么设想过。但是HINSTANCE hInst;设置为成员我到是知道 mGg G=(mGg)GetProcAddress(hInst,"G"); 这个要在那里设定呢?在Oninitdialog()里?刚爬起来,没太理解[/quote] 都放在Oninitdialog里 加载一次 释放一次 你可以多次使用导出的函数[/quote] 如果是多次使用,最好的当然是程序启动加载DLL,程序退出时释放DLL[/quote] 我用AfxLoadLibrary在Oninitdialog()中加载了DLL,在过程函数中 typedef CString (_stdcall *mGg)(CString W, CString R, int i,int iW); mGg G=(mGg)GetProcAddress(hInst,"G"); if(!G) { AfxMessageBox(_T("sru-获取函数地址失败!")); return; } str = G(strU,strR,iT,iW); 调用DLL的导出函数。在程序退出时释放掉了DLL。但是在Ontimer,每1分钟刷新一次时,DLL很容易出现内存错误 在程序退出后,释放DLL时还会出现内存泄漏。郁闷
hushoubo 2014-04-22
  • 打赏
  • 举报
回复
引用 11 楼 WUYUAN2011WOAINI 的回复:
[quote=引用 10 楼 rundll64 的回复:] [quote=引用 9 楼 zzdmfk 的回复:] [quote=引用 7 楼 rundll64 的回复:] [quote=引用 6 楼 zzdmfk 的回复:] 最好不要重复这样做。可以程序运行即loadlibrary,结束时freelibrary. 不然同步起来。
我也在考虑这个问题,不过不会这么弄,能给段demo看看吗? [/quote] 这两个做全局变量或没访问限制的变量: HINSTANCE hInst; mGg G=(mGg)GetProcAddress(hInst,"G"); 对话框的oninitdialog()里: hinst=loadlibrary......; G=(mGg)GetProcAddress(hInst,"G"); 对话框类的onclose里面: freelibrary; [/quote] 嗯嗯,我也是这么设想过。但是HINSTANCE hInst;设置为成员我到是知道 mGg G=(mGg)GetProcAddress(hInst,"G"); 这个要在那里设定呢?在Oninitdialog()里?刚爬起来,没太理解[/quote] 都放在Oninitdialog里 加载一次 释放一次 你可以多次使用导出的函数[/quote] 如果是多次使用,最好的当然是程序启动加载DLL,程序退出时释放DLL
kuankuan_qiao 2014-04-22
  • 打赏
  • 举报
回复
引用 10 楼 rundll64 的回复:
[quote=引用 9 楼 zzdmfk 的回复:] [quote=引用 7 楼 rundll64 的回复:] [quote=引用 6 楼 zzdmfk 的回复:] 最好不要重复这样做。可以程序运行即loadlibrary,结束时freelibrary. 不然同步起来。
我也在考虑这个问题,不过不会这么弄,能给段demo看看吗? [/quote] 这两个做全局变量或没访问限制的变量: HINSTANCE hInst; mGg G=(mGg)GetProcAddress(hInst,"G"); 对话框的oninitdialog()里: hinst=loadlibrary......; G=(mGg)GetProcAddress(hInst,"G"); 对话框类的onclose里面: freelibrary; [/quote] 嗯嗯,我也是这么设想过。但是HINSTANCE hInst;设置为成员我到是知道 mGg G=(mGg)GetProcAddress(hInst,"G"); 这个要在那里设定呢?在Oninitdialog()里?刚爬起来,没太理解[/quote] 都放在Oninitdialog里 加载一次 释放一次 你可以多次使用导出的函数
rundll64 2014-04-22
  • 打赏
  • 举报
回复
引用 9 楼 zzdmfk 的回复:
[quote=引用 7 楼 rundll64 的回复:] [quote=引用 6 楼 zzdmfk 的回复:] 最好不要重复这样做。可以程序运行即loadlibrary,结束时freelibrary. 不然同步起来。
我也在考虑这个问题,不过不会这么弄,能给段demo看看吗? [/quote] 这两个做全局变量或没访问限制的变量: HINSTANCE hInst; mGg G=(mGg)GetProcAddress(hInst,"G"); 对话框的oninitdialog()里: hinst=loadlibrary......; G=(mGg)GetProcAddress(hInst,"G"); 对话框类的onclose里面: freelibrary; [/quote] 嗯嗯,我也是这么设想过。但是HINSTANCE hInst;设置为成员我到是知道 mGg G=(mGg)GetProcAddress(hInst,"G"); 这个要在那里设定呢?在Oninitdialog()里?刚爬起来,没太理解
路人乙2019 2014-04-21
  • 打赏
  • 举报
回复
引用 7 楼 rundll64 的回复:
[quote=引用 6 楼 zzdmfk 的回复:] 最好不要重复这样做。可以程序运行即loadlibrary,结束时freelibrary. 不然同步起来。
我也在考虑这个问题,不过不会这么弄,能给段demo看看吗? [/quote] 这两个做全局变量或没访问限制的变量: HINSTANCE hInst; mGg G=(mGg)GetProcAddress(hInst,"G"); 对话框的oninitdialog()里: hinst=loadlibrary......; G=(mGg)GetProcAddress(hInst,"G"); 对话框类的onclose里面: freelibrary;
rundll64 2014-04-21
  • 打赏
  • 举报
回复
引用 4 楼 zzz3265 的回复:
也不一定要改隐式连接, 直接去掉 FreeLibrary(hInst); 就好了, 这样看看是否有问题
你说的方法我测试了,如果不释放掉,长时间运行时会出问题

 CString str;
    HINSTANCE hInst;
    hInst=LoadLibrary(_T("te.dll"));
    typedef CString (_stdcall *mGg)(CString W, CString R, int i,int iW);
    mGg G=(mGg)GetProcAddress(hInst,"G");
    if(!G)
    {
        AfxMessageBox(_T("sru-获取函数地址失败!"));
        return;
    }
    str = G(strU,strR,iT,iW);
        。。。。。。。。
我的这个DLL是专门获取网页的,哎,估计可能是获取网页那里处理的不好,在不释放的情况下,快速执行几次程序就非了
rundll64 2014-04-21
  • 打赏
  • 举报
回复
引用 6 楼 zzdmfk 的回复:
最好不要重复这样做。可以程序运行即loadlibrary,结束时freelibrary. 不然同步起来。
我也在考虑这个问题,不过不会这么弄,能给段demo看看吗?
路人乙2019 2014-04-21
  • 打赏
  • 举报
回复
最好不要重复这样做。可以程序运行即loadlibrary,结束时freelibrary. 不然同步起来。
rundll64 2014-04-21
  • 打赏
  • 举报
回复
我的程序通过settimer,每10分钟刷新一次页面,动态获取网页的内容 每一次我都是LoadLibary调用,用完了就释放了。在这种情况下,出现的问题就是在查询存储过程中发现会有阻塞的现象 例如某一个时间段没有获取到数据。但是在20分钟的时候获取到了。 现在我用隐式连接,内存泄漏的问题到是没有了。但是出现的问题,就是上面我贴出来的那个atltrace.h文件中的一段代码。提示它出错。之前从来没有发现过。头疼啊
Yofoo 2014-04-21
  • 打赏
  • 举报
回复
也不一定要改隐式连接, 直接去掉 FreeLibrary(hInst); 就好了, 这样看看是否有问题
rundll64 2014-04-21
  • 打赏
  • 举报
回复
引用 2 楼 zzz3265 的回复:
没有产生返回值, 是指程序一直阻塞在那里吗? 如果是这样, 就是这个Dll的问题, 应该把情况反映给这个Dll的开发人员 另外 LoadLibrary 除非特殊情况不要 FreeLibrary, LoadLibrary 会耗费比较大的系统资源, 另外 DLL自己的初始化代码, 卸载代码如果不好, 容易造成资源泄漏, 重复LoadLibrary , FreeLibrary, 会把这些错误放大
内存泄漏的问题我确实发现了,我现在改成了隐式连接,内存泄漏问题到是不出现了 但是却出现了个更头大的问题,就是在atltrace.h文件中

inline bool IsTracingEnabled(DWORD_PTR dwCategory, UINT nLevel)
{
	return CTrace::IsTracingEnabled(dwCategory, nLevel);
}

    inline void __cdecl CTrace::TraceV(const char *pszFileName, int nLine,
		DWORD_PTR dwCategory, UINT nLevel, LPCSTR pszFmt, va_list args) const
	{
		AtlTraceVA(m_dwModule, pszFileName, nLine, dwCategory, nLevel, pszFmt, args);
	}
	inline void __cdecl CTrace::TraceV(const char *pszFileName, int nLine,
		DWORD_PTR dwCategory, UINT nLevel, LPCWSTR pszFmt, va_list args) const
	{
		AtlTraceVU(m_dwModule, pszFileName, nLine, dwCategory, nLevel, pszFmt, args);
	}

extern CTraceCategory atlTraceGeneral;
产生了错误,找了半天了 还有啊,如果用LoadLibrary 加载后的DLL如果不释放,不占用内存吗? 因为我的这个DLL同时要被调用10多次,而且每一次传递的参数都不一样,如果我不释放掉它,会不会出问题呢?
Yofoo 2014-04-21
  • 打赏
  • 举报
回复
没有产生返回值, 是指程序一直阻塞在那里吗? 如果是这样, 就是这个Dll的问题, 应该把情况反映给这个Dll的开发人员 另外 LoadLibrary 除非特殊情况不要 FreeLibrary, LoadLibrary 会耗费比较大的系统资源, 另外 DLL自己的初始化代码, 卸载代码如果不好, 容易造成资源泄漏, 重复LoadLibrary , FreeLibrary, 会把这些错误放大
加载更多回复(1)

15,467

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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