关于进程中同时动态加载同一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);


...全文
677 21 打赏 收藏 转发到动态 举报
写回复
用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)
程序名称:OllyDBG版 本:1.10汉 化 人:cao_cong联系方式:cao_cong_hx@yahoo.com.cn汉化日期:2005.11.28汉化说明: 本来是想等 OllyDBG 2.0 出来再汉化的,可看到dyk158兄弟的修改版说明对我原来汉化版本的汉化质量提了一点小小的意见,想想也是,我原来的汉化版是OllyDBG 1.10 的最终版本刚出来时汉化的,距今已经一年多了也没有更新过,当时只顾不出因汉化造成的Bug,汉化嘛确实不咋的。看到BoOMBoX/TSRh2004他们制作的美化界面,确实也觉得漂亮,最后决定再出个汉化版本。这个版本的汉化测试、修改花了我整整两个星期的业余时间,其的非标字符对照文本有4000多行,看一遍都半天。这个版本的所有翻译我都重新过了几遍,绝大部分都重新翻译过,力求做到准确,希望能给大家一个比较完美的汉化版本。在制作过程参考了TT小组翻译的OllyDBG帮助及dyk158修改、聆风听雨汉化的ODbyDYK修改版,主要是想让翻译更准确一点,能让新手把汉化版和TT小组汉化的帮助文档对照起来学习。在此对以上提到的各位表示衷心的感谢! 这个软件汉化起来确实是个苦差事,不光是要翻译的资源多,还有一个重要的方面就是稍不留神就会出现汉化引起的Bug。经常是用原版来调试汉化版找问题,象原来菜单上的“&Window”汉化后会出错,还是调试后才知道原来它内部菜单时还有个这个“&Window”,只有两个都汉化才不会出错。另外其它的许多问题都只好靠调试来解决。原来汉化时又没有把要注意的地方写下来,这次光测试就花了好几天。 这个汉化版本除因汉化必要而打补丁外,我不准备再对它打任何补丁。一是我怕打补丁影响 OllyDBG 的兼容性;二是已经有Fly和dyk158他们做了,我想我自己再做的话也不会比他们做的更好;三是我实在是感到太累了!如果大家要想要修改的版本的话,推荐使用freecat兄弟制作的AutoPath,我把这个插件放在 FixOD 目录下,我把freecat兄弟发布时所用的说明也放在同一目录下,大家可以根据说明来使用这个插件改造你的OllyDBG。 在这里我要感谢看雪论坛上的看雪老大和论坛上各位兄弟的支持,正是有了他们的测试和建议,经过多次修正后,才有了今天的这个最终版本,由衷的感谢看雪论坛上的各位兄弟!汉化第二版主要更新:1、界面采用 BoOMBoX/TSRh2004 制作的美化界面,主要为了好看一点。2、绝大部分句子都重新翻译过,力求做到准确。3、配置文件除字体、语法高亮、颜色这几个部分保留为文外,其它的都恢复为英文。保留字体、语法高亮、颜色这几个部分为文的目的是因为我发现若先运行过英文版配置好后,汉化版对应这几个部分的一些菜单也会取原英文版配置的英文字串,而不是汉化过的字串。我觉得翻译后既能保持与英文版的兼容性,又能让英文版与文版的界面等互不干扰。4、dyk158 建议我把配置文件的字体、语法高亮、颜色这几个部分恢复为英文,我专门做了个恢复为英文配置的补丁(如果你以前运行过英文版进行了相应配置,则补丁后的汉化版本对应这几个部分的相应菜单将会显示英文,若你是用打过这个补丁的汉化版本生成配置文件,则相应菜单将会显示文)放在英文配置补丁目录下,需要字体、语法高亮、颜色这部分也用英文配置的朋友可以把这个补丁放到我做的汉化版的安装目录,选择 Ollydbg.exe 补丁就可以了。这个补丁同样适用于原版界面的汉化版本。5、上一版部分未汉化的内容这次除了不能汉化的外,基本上都已汉化。6、另有一个界面未作美化的汉化版放在原版界面目录,可以按自己的喜好选择使用哪一个。7、FixOD 目录下放的是用 freecat 的 AutoPath.dll 打过补丁的 OllyDBG,使用前请先备份好你原来的Ollydbg.exe文件,再把这个目录下的Ollydbg.exe、AutoPath.dll、AutoPath.ini复制到你的OllyDBG安装目录下就可以了。在上一版的基础上,插件做了如下更新:1、脚本插件 ODbgScript.dll (v1.23 汉化版)2、快捷命令插件 CmdBar.dll (v3.10.109c 汉化版,这个版本有支持运行 OllyScript 脚本的命令:OSC)3、标签插件 Labeler.dll (v1.33.108 汉化版)4、图表插件 OllyFlow.dll (v0.71 汉化版,我从IDA提取了个wingraph32.exe放在插件目录下,用于配合这个插件)5、断点管理 olly_bp_man.dll (汉化版,在我机器上不能用,放在备用目录)6、字串参考修改版本 ustrrefadd.dll (汉化版)另外还添了dyk158 汉化的两个插件:1、脱壳插件 OllyDump.dll (V3.00.110 dyk158 汉化版)2、脱壳插件 pedumper.dll (v3.03 dyk158 汉化版) 推荐大家试用一下这两个插件:ApiBreak 插件,用于在对话框、字串、注册表、时间、内存等 API 函数上设置断点,还可设置万能断点,简单易用;GODUP 插件,包含 Map 入器、资源查看器、进程查看器、IDA 签名入程序及自带的一个记事本这五个工具。感觉它自带的记事本用来在调试时记一些东西比较方便。 如果你以前没用过OllyDBG的话,我要提醒你使用前先在菜单的 选项->界面->目录 把插件和 UDD 的路径设置好,以免影响使用! 此汉化版的插件除了一个 PuntosMagicos.dll 插件没汉化外(我实在是弄不懂是哪国语言),其它的插件都已汉化。目录下的OLLYDBG.HLP帮助文件是由TT小组翻译的文帮助,在此对TT小组的辛勤劳动表示感谢!(OLLYDBG_EN.HLP为原版英文帮助)声明: 1.本汉化软件包内的所有英文及其他语言的源程序的版权归原作者(公司)所有。 2.本人不对使用本汉化软件造成的任何情况的损失负责。 3.本汉化软件仅供学习研究之用。严禁用于商业用途。本人不对使用本汉化软件造成的任何法律纠纷负责。 4.如果你对本汉化软件有什么建议请联系我。 5.请在转时保留此汉化版的完整性。

15,471

社区成员

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

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