求助C++ Builder2010编写的应用调用了dll问题

billy000 2020-03-24 07:23:44
各位大神,小白求助一下,我用cb2010写的应用里面,把其中一段处理方式改造成了dll,改造完成后程序运行及处理完全正常,问题是凡是涉及到调用了dll的操作之后,关闭程序时进程就不会结束,只能在任务管理器里面杀进程才会结束,进行的操作不涉及dll调用方法就没问题,可以正常关闭,因此感觉问题出在dll没有被正确释放,因此求助各位大大,我的调用及释放是不是有问题?应该怎么修正呢?分值不多,谢谢!

调用及释放代码如下(想法是只在需要的时候才调用dll,每次调用完之后立即释放,但不确定方法对没有,方法来自百度后自行改造
HINSTANCE Hdl;
newp_funpath = ExtractFilePath(Application->ExeName) + "Reload.dll";
// 定义函数原型
Hdl = ::LoadLibrary(newp_funpath.c_str()); // 载入DLL
if (Hdl != NULL) {
log_reason = (AnsiString __stdcall(*)(AnsiString,
AnsiString))::GetProcAddress(Hdl, "logreason");
// 获取函数入口地址
if (log_reason != NULL) {
newp_reason = log_reason(newp_dev_ip, newp_log_source);
}
else {
ShowMessage("Reload.dll读取失败!请检查程序完整性!");
}
log_reason = NULL;
FreeLibrary(log_reason); // 释放dll
log_reason = NULL;
Hdl = NULL;
::FreeLibrary(Hdl); // 释放dll
delete Hdl;


附:DLL部分代码:
extern "C" __declspec(dllexport)  AnsiString __stdcall logreason(AnsiString log_dev_ip, AnsiString logresource)    // 纵向告警原因判定函数
{
AnsiString newp_func_inipath, newp_func_ws_dm, newp_func_ws_n;
.................省略中间过程代码..............
newp_func_ado->Close(); //关闭过程中临时创建的的ado连接
newp_func_ado->SQL->Clear(); //清空sql语句
delete newp_func_ado;删除ado
}
return(newp_func_src_data_net_p + "." + newp_func_dev_data_net_p + "." + newp_func_dst_data_net_p + "." + newp_func_logtype); //返回结果字符串
}
...全文
361 13 打赏 收藏 举报
写回复
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
Behard 2020-04-10
一般来说 ADOquery 使用方法:
ADOquery1 = new TADOquery(NULL); // or 一个窗口 Handle
ADOQuery1->ConnectionString = ... ...

ADOQuery1->SQL->Clear();
ADOQuery1->Prepared=false;
ADOQuery1->SQL->Add(... ...);
ADOQuery1->Prepared=true;
ADOQuery1->ExecSQL(); // Or
ADOQuery1->Open();

... ...

ADOQuery1->Close();
delete ADOQuery1;
  • 打赏
  • 举报
回复
billy000 2020-04-09
各位大大...求助指点下小白呀
  • 打赏
  • 举报
回复
ooolinux 2020-03-30
不懂,我直接在窗体放的连接,如果你是new的,就用delete。
  • 打赏
  • 举报
回复
billy000 2020-03-30
引用 9 楼 ooolinux 的回复:
[quote=引用 7 楼 billy000 的回复:] 谢谢解答,确实我用的是ADOquery,newp_func_ado->Close()这一句不是关闭了吗?还是说我必须得用newp_func_ado->Connection->Close()这样来关闭呢?我晚点试着用后者试试
一个数据集关闭,一个连接关闭,不是一回事。[/quote] 我把newp_func_ado->Close()改为newp_func_ado->Connection->Close()的时候,程序执行直接就报dll内存错了,感觉就是这句连接关闭有问题我试过用newp_func_ado->Free()好像也不行,各种组合试的有点多了...求下面释放ADOquery的正确顺序应该是啥
newp_func_ado->Close();
			newp_func_ado->SQL->Clear();
			newp_func_ado->SQL->Add(newp_func_sql);
			newp_func_ado->Open();
                        

                       newp_func_ado->SQL->Clear();
			//newp_func_ado->Close();
			newp_func_ado->Connection->Close();
			//newp_func_ado->Connection->Destroying();
			newp_func_ado->Free();
			//FreeLibrary(newp_func_ado);
			delete newp_func_ado;
  • 打赏
  • 举报
回复
ooolinux 2020-03-30
引用 7 楼 billy000 的回复:
谢谢解答,确实我用的是ADOquery,newp_func_ado->Close()这一句不是关闭了吗?还是说我必须得用newp_func_ado->Connection->Close()这样来关闭呢?我晚点试着用后者试试
一个数据集关闭,一个连接关闭,不是一回事。
  • 打赏
  • 举报
回复
billy000 2020-03-30
引用 6 楼 Behard 的回复:
[quote=引用 5 楼 zhgwbzhd 的回复:] ::LoadLibrary,加载DLL,需要FreeLibrary来释放。 ::GetProcAddress只是找到入口,找到后调用即可,没有配套释放。 以上的应该还不是问题的关键, AnsiString newp_func_inipath, newp_func_ws_dm, newp_func_ws_n; .................省略中间过程代码.............. newp_func_ado->Close(); //关闭过程中临时创建的的ado连接 newp_func_ado->SQL->Clear(); //清空sql语句 delete newp_func_ado;删除ado } 这是你的DLL,看代码你只是释放和删除了ADO(可能是查询ADOquery),但是ADOConnect没看到你的删除在哪里。 应该是ADO链接还存在,造成不能完全释放。
1. 确实不需要 FreeLibrary 函数名 2. 建议谁申请的内存,谁释放,意思就是 Exe 申请的Exe 释放,DLL 申请的 DLL 释放,不过这个仅仅是建议,没有强制,一般这样使用,如果你不是这样,最好注明一下[/quote] 谢谢,主要是这个怎么实现释放一直不了解...求大神指点
  • 打赏
  • 举报
回复
billy000 2020-03-30
引用 5 楼 zhgwbzhd 的回复:
::LoadLibrary,加载DLL,需要FreeLibrary来释放。 ::GetProcAddress只是找到入口,找到后调用即可,没有配套释放。 以上的应该还不是问题的关键, AnsiString newp_func_inipath, newp_func_ws_dm, newp_func_ws_n; .................省略中间过程代码.............. newp_func_ado->Close(); //关闭过程中临时创建的的ado连接 newp_func_ado->SQL->Clear(); //清空sql语句 delete newp_func_ado;删除ado } 这是你的DLL,看代码你只是释放和删除了ADO(可能是查询ADOquery),但是ADOConnect没看到你的删除在哪里。 应该是ADO链接还存在,造成不能完全释放。
谢谢解答,确实我用的是ADOquery,newp_func_ado->Close()这一句不是关闭了吗?还是说我必须得用newp_func_ado->Connection->Close()这样来关闭呢?我晚点试着用后者试试
  • 打赏
  • 举报
回复
Behard 2020-03-28
引用 5 楼 zhgwbzhd 的回复:
::LoadLibrary,加载DLL,需要FreeLibrary来释放。

::GetProcAddress只是找到入口,找到后调用即可,没有配套释放。

以上的应该还不是问题的关键,

AnsiString newp_func_inipath, newp_func_ws_dm, newp_func_ws_n;
.................省略中间过程代码..............
newp_func_ado->Close(); //关闭过程中临时创建的的ado连接
newp_func_ado->SQL->Clear(); //清空sql语句
delete newp_func_ado;删除ado
}

这是你的DLL,看代码你只是释放和删除了ADO(可能是查询ADOquery),但是ADOConnect没看到你的删除在哪里。
应该是ADO链接还存在,造成不能完全释放。


1. 确实不需要 FreeLibrary 函数名

2. 建议谁申请的内存,谁释放,意思就是 Exe 申请的Exe 释放,DLL 申请的 DLL 释放,不过这个仅仅是建议,没有强制,一般这样使用,如果你不是这样,最好注明一下
  • 打赏
  • 举报
回复
billy000 2020-03-26
引用 2 楼 Behard 的回复:
两个问题 1. LoadLibrary,调研函数后,直接 FreeLibrray 即可 2. 不建议使用 AnsiString 作为 DLL 参数或者返回值使用,而采用 char * 等标准类型,需注意局部变量返回无效的问题 C++ Builder 的描述: // Important note about DLL memory management when your DLL uses the // static version of the RunTime Library: // // If your DLL exports any functions that pass String objects (or structs/ // classes containing nested Strings) as parameter or function results, // you will need to add the library MEMMGR.LIB to both the DLL project and // any other projects that use the DLL. You will also need to use MEMMGR.LIB // if any other projects which use the DLL will be performing new or delete // operations on any non-TObject-derived classes which are exported from the // DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling // EXE's to use the BORLNDMM.DLL as their memory manager. In these cases, // the file BORLNDMM.DLL should be deployed along with your DLL. // // To avoid using BORLNDMM.DLL, pass string information using "char *" or // ShortString parameters. // // If your DLL uses the dynamic version of the RTL, you do not need to // explicitly add MEMMGR.LIB as this will be done implicitly for you //---------------------------------------------------------------------------
谢谢!根据您的提示,我把AnsiString 换为char*返回,可以正常执行,但dll释放还是有问题,直接释放的时候就是释放不了....请问下一步我该往哪个方向查?dll里面所有用到的组件在里面我都全部删掉了,除了ansistring没删以外,应该就没有任何资源占用了呀?
  • 打赏
  • 举报
回复
billy000 2020-03-26
引用 1 楼 早打大打打核战争 的回复:
这三行删掉: log_reason = NULL; FreeLibrary(log_reason); // 释放dll log_reason = NULL; 这么释放库属于脑残了么: Hdl = NULL; ::FreeLibrary(Hdl); // 释放dll
我也知道这样NULL之后再释放不合适,但现在有个问题是如果我不先NULL再释放,那么dll根本就释放不了.....DLL里面调用的所有VCL我都全部停掉了的,第一次改写dll,所以这个确实不太明白我把代码改成下面这样后,程序到 ::FreeLibrary(Hdl);这一步就走不了了,表现为消息1有,消息2就没了:

					//log_reason = NULL;
					FreeLibrary(log_reason); // 释放dll
					//log_reason = NULL;
					//Hdl = NULL;
					ShowMessage("1");  //1会弹出
					::FreeLibrary(Hdl); // 释放dll   //这儿释放出问题了....
					ShowMessage("2"); //2就没有了
					delete Hdl;
					//Hdl = NULL;
					// ::FreeLibrary(Hdl); // 一定不要忘记调用完毕后释放DLL
  • 打赏
  • 举报
回复
zhgwbzhd 2020-03-26
::LoadLibrary,加载DLL,需要FreeLibrary来释放。 ::GetProcAddress只是找到入口,找到后调用即可,没有配套释放。 以上的应该还不是问题的关键, AnsiString newp_func_inipath, newp_func_ws_dm, newp_func_ws_n; .................省略中间过程代码.............. newp_func_ado->Close(); //关闭过程中临时创建的的ado连接 newp_func_ado->SQL->Clear(); //清空sql语句 delete newp_func_ado;删除ado } 这是你的DLL,看代码你只是释放和删除了ADO(可能是查询ADOquery),但是ADOConnect没看到你的删除在哪里。 应该是ADO链接还存在,造成不能完全释放。
  • 打赏
  • 举报
回复
这三行删掉:
log_reason = NULL;
FreeLibrary(log_reason); // 释放dll
log_reason = NULL;

这么释放库属于脑残了么:
Hdl = NULL;
::FreeLibrary(Hdl); // 释放dll
  • 打赏
  • 举报
回复
Behard 2020-03-25
两个问题
1. LoadLibrary,调研函数后,直接 FreeLibrray 即可

2. 不建议使用 AnsiString 作为 DLL 参数或者返回值使用,而采用 char * 等标准类型,需注意局部变量返回无效的问题

C++ Builder 的描述:
// Important note about DLL memory management when your DLL uses the
// static version of the RunTime Library:
//
// If your DLL exports any functions that pass String objects (or structs/
// classes containing nested Strings) as parameter or function results,
// you will need to add the library MEMMGR.LIB to both the DLL project and
// any other projects that use the DLL. You will also need to use MEMMGR.LIB
// if any other projects which use the DLL will be performing new or delete
// operations on any non-TObject-derived classes which are exported from the
// DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
// EXE's to use the BORLNDMM.DLL as their memory manager. In these cases,
// the file BORLNDMM.DLL should be deployed along with your DLL.
//
// To avoid using BORLNDMM.DLL, pass string information using "char *" or
// ShortString parameters.
//
// If your DLL uses the dynamic version of the RTL, you do not need to
// explicitly add MEMMGR.LIB as this will be done implicitly for you
//---------------------------------------------------------------------------
  • 打赏
  • 举报
回复
发帖
VCL组件使用和开发

593

社区成员

C++ Builder VCL组件使用和开发
社区管理员
  • VCL组件使用和开发社区
加入社区
帖子事件
创建了帖子
2020-03-24 07:23
社区公告
暂无公告