求救!XML内存不释放以及DLL动态调用的问题
兄弟们,求教啊!
问题的起因是这样的,需要在程序中动态切换语言。我将语言配置文件以xml格式保存在不同路径下(Line-Node-Function三级目录,我们软件的结构要求),当需要切换到指定语言时,就卸载当前语言设定,加载新的语言。相关的函数以字典DLL格式存在,然后就发现每次切换完语言,系统内存就会泄漏一块,检查到最后,发现是调用msxml的load后,内存就会增大,这是正常的,因为要将文件内容临时存到文档对象里,但问题是,当DLL调用结束,相关对象已经析构了,这片内存依然存在,没有释放,于是乎,每切换一次语言,就泄漏一片内存。查了很多资料,有一个微软的工程师在某个回复中说,MSXML有自己的内存管理方式,不能直接释放,但是当模块结束时,会自己释放内存。换句话说,当这个字典DLL被释放后,XML load的内存会释放。
Load_XML_Document(LPCTSTR strFileName, bool blParser)
{
m_strLasterror = m_strOK;
// 复位文档相关设置
//
this->Reset_XML_Document();
// 将文件完整路径由CString转化为BSTR,XML使用的是COM
//
CString sFileName = strFileName;
_bstr_t bstrFileName;
bstrFileName = sFileName.AllocSysString();
// 调用 IXMLDOMDocumentPtr 的 load 函数加载XML文档
//
variant_t vResult;
// 就是这个地方,内存会增大很多!!!!!!!!!!!!!!!
vResult = m_plDomDocument->load(bstrFileName);
if( ((bool)vResult) == TRUE ) // success!
{
// 文档已加载,初始化根节点指针
//
m_pDocRoot = m_plDomDocument->documentElement;
// 当前遍历深度
this->m_iXMLDepth = 1;
// 解析文档
//
if ( blParser )
{
//Parse_Objects(m_plDomDocument);
Parse_Objects(m_pDocRoot);
}
// 重新指向根节点
this->Go_to_Root();
return true;
}
else
{ // 未能加载XML文档,设置错误信息,返回false
//
m_strLasterror = _T("XML Document FAILED to load");
return false;
}
}
问题就来了,我是在EXE里静态调用的DLL,在程序开始时就加载了lib,结束时才释放,那这个dll会伴随程序的整个周期,所以内存一直不会被释放。用了很多办法,什么release等,都不能释放。
我现在试着全部改成动态调用,想看看这样内存能不能释放,要不然,我只能改变配置文件的格式,用ini文件重写了。但是,动态调用时,GetProcAddress函数一直报127错误,说是找不到函数!
我在DLL里编写时,所有函数均是以C格式输出的,如下:
#define TDRDICAPI extern "C" __declspec(dllexport)
...
TDRDICAPI DWORD __stdcall dicLoadDictionary( BYTE n, BYTE f )
{
return g_oDic.LoadDictionary(n, f);
}
在静态加载、调用时,一切正常,如下:
#include "TDRDic.h"
#pragma comment(lib,"TDRDLLDic.lib")
...
{
...
DWORD status = dicLoadDictionary(n, f);
}
改成动态调用后,如下:
HINSTANCE hInst = LoadLibrary(_T("TDRDLLDic.dll"));
// HINSTANCE hInst = LoadLibrary(_T("z:\\Works\\TULIP\\TULIP\\Lib\\TDRDLLDic.dll"));
if (hInst)
{
pfLoadDic func = (pfLoadDic) GetProcAddress(hInst, "dicLoadDictionary");
if (func)
{
status = (*func)(n,f);
}
else
{
err = GetLastError();
}
FreeLibrary(hInst);
}
LoadLibrary成功,GetProcAddress就是报127的错误,找不到函数。
查看DLL输出,发现是以C++格式输出的,_dicLoadDictionary@8,这就很奇怪了,我在定义函数时,已经是 extern "c"格式了,为什么会这样?
所以两个问题求教:
1。如果使用静态DLL,那怎么样能让那个xml释放掉!
2。如果动态加载,这个函数名怎么了。。。。
问题的起因是这样的,需要在程序中动态切换语言。我将语言配置文件以xml格式保存在不同路径下(Line-Node-Function三级目录,我们软件的结构要求),当需要切换到指定语言时,就卸载当前语言设定,加载新的语言。相关的函数以字典DLL格式存在,然后就发现每次切换完语言,系统内存就会泄漏一块,检查到最后,发现是调用msxml的load后,内存就会增大,这是正常的,因为要将文件内容临时存到文档对象里,但问题是,当DLL调用结束,相关对象已经析构了,这片内存依然存在,没有释放,于是乎,每切换一次语言,就泄漏一片内存。查了很多资料,有一个微软的工程师在某个回复中说,MSXML有自己的内存管理方式,不能直接释放,但是当模块结束时,会自己释放内存。换句话说,当这个字典DLL被释放后,XML load的内存会释放。
Load_XML_Document(LPCTSTR strFileName, bool blParser)
{
m_strLasterror = m_strOK;
// 复位文档相关设置
//
this->Reset_XML_Document();
// 将文件完整路径由CString转化为BSTR,XML使用的是COM
//
CString sFileName = strFileName;
_bstr_t bstrFileName;
bstrFileName = sFileName.AllocSysString();
// 调用 IXMLDOMDocumentPtr 的 load 函数加载XML文档
//
variant_t vResult;
// 就是这个地方,内存会增大很多!!!!!!!!!!!!!!!
vResult = m_plDomDocument->load(bstrFileName);
if( ((bool)vResult) == TRUE ) // success!
{
// 文档已加载,初始化根节点指针
//
m_pDocRoot = m_plDomDocument->documentElement;
// 当前遍历深度
this->m_iXMLDepth = 1;
// 解析文档
//
if ( blParser )
{
//Parse_Objects(m_plDomDocument);
Parse_Objects(m_pDocRoot);
}
// 重新指向根节点
this->Go_to_Root();
return true;
}
else
{ // 未能加载XML文档,设置错误信息,返回false
//
m_strLasterror = _T("XML Document FAILED to load");
return false;
}
}
问题就来了,我是在EXE里静态调用的DLL,在程序开始时就加载了lib,结束时才释放,那这个dll会伴随程序的整个周期,所以内存一直不会被释放。用了很多办法,什么release等,都不能释放。
我现在试着全部改成动态调用,想看看这样内存能不能释放,要不然,我只能改变配置文件的格式,用ini文件重写了。但是,动态调用时,GetProcAddress函数一直报127错误,说是找不到函数!
我在DLL里编写时,所有函数均是以C格式输出的,如下:
#define TDRDICAPI extern "C" __declspec(dllexport)
...
TDRDICAPI DWORD __stdcall dicLoadDictionary( BYTE n, BYTE f )
{
return g_oDic.LoadDictionary(n, f);
}
在静态加载、调用时,一切正常,如下:
#include "TDRDic.h"
#pragma comment(lib,"TDRDLLDic.lib")
...
{
...
DWORD status = dicLoadDictionary(n, f);
}
改成动态调用后,如下:
HINSTANCE hInst = LoadLibrary(_T("TDRDLLDic.dll"));
// HINSTANCE hInst = LoadLibrary(_T("z:\\Works\\TULIP\\TULIP\\Lib\\TDRDLLDic.dll"));
if (hInst)
{
pfLoadDic func = (pfLoadDic) GetProcAddress(hInst, "dicLoadDictionary");
if (func)
{
status = (*func)(n,f);
}
else
{
err = GetLastError();
}
FreeLibrary(hInst);
}
LoadLibrary成功,GetProcAddress就是报127的错误,找不到函数。
查看DLL输出,发现是以C++格式输出的,_dicLoadDictionary@8,这就很奇怪了,我在定义函数时,已经是 extern "c"格式了,为什么会这样?
所以两个问题求教:
1。如果使用静态DLL,那怎么样能让那个xml释放掉!
2。如果动态加载,这个函数名怎么了。。。。
...全文
相关推荐
java调用C++动态链接库dll接口
本项目涉及的"java调用C++动态链接库dll接口"是解决这种跨语言交互问题的一种方法,主要利用了Java Native Interface(JNA)这一技术。
LabVIEW调用.NET DLL完整实现指南
LabVIEW作为图形化编程环境,广泛应用于测试测量、工业自动化和控制系统开发中。随着软件架构的复杂化,仅依靠LabVIEW内置函数库已难以满足高级数据处理和通信需求。.NET平台凭借其丰富的类库和跨语言集成能力,成为LabVIEW扩展功能的重要桥梁。通过调用.NET DLL,LabVIEW项目可直接复用C#、VB.NET等语言编写的成熟逻辑,实现高性能算法、数据库操作、网络通信等功能。这种跨平台调用机制不仅提升了开发效率,也增强了系统的可维护性与扩展性,成为现代LabVIEW工程不可或缺的一部分。
java实现百望税控NISEC_SKSC.dll接口调用发送xml报文
本文介绍了如何使用Java语言调用百望税控的DLL接口,并通过发送XML报文实现相关功能。重点讲解了接口调用方法及数据传输过程。
NXopen二次开发将读取xml文件函数封装为dll方便调用
本案例中,我们关注的是使用NXopen工具包进行的二次开发,目的是将读取XML文件的函数封装到一个动态链接库(DLL)中,以便于其他程序便捷地调用。下面将详细介绍这一过程及其相关知识点。
C++调用C#实现Xml读写
总结起来,C++调用C#实现XML读写是一个涉及多方面技术的问题,包括跨语言接口设计、类型转换、DLL动态加载和XML操作。


HTML/XML
