mfc自定义控件返回字符串接口的问题

red-fly 2017-12-19 08:59:32
在支持MFC的ActiveX中,添加了一个接口,名称为 GetLayoutList,返回一个字符串。
代码如下:


BSTR CxxCtrl::GetLayoutList(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString strResult = TEXT("WINDOWLIST:1,2,3,4,5,6");
return strResult.AllocSysString();
}

控件在加载的时候会调用此接口。
但是发现似乎总是挂掉,可能发生在控件加的时候,也可能发生在控件卸载的时候。这个问题目前发生在win10+ie11上,而win7+ie11基本不出现问题。
此问题是根据最近调试确定的,因为修改此接口的代码,会影响挂掉的频率。

根据说明,上面的代码只分配内存不释放,理论上最多只是发生内存泄露而不应该挂掉才对。
为了解决这个内存泄露的问题,这个字符串的内存分配放到了CxxApp中:
在 CxxApp中声明一个public类型的变量:
BSTR m_layoutList;
在 BOOL CxxApp::InitInstance()中分配:

BOOL CxxApp::InitInstance()
{
BOOL bInit = COleControlModule::InitInstance();
CString strResult = TEXT("WINDOWLIST:1,2,3,4,5,6");
m_layoutList = strResult.AllocSysString();
return bInit;
}

在控件退出的时候清除:

int CxxApp::ExitInstance()
{
SysFreeString(m_layoutList);
m_layoutList = NULL;
}

在对应的接口中直接返回这个字符串:

BSTR CxxCtrl::GetLayoutList(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return theApp.m_layoutList;
}

即使这样修改,还是会挂掉,只是
...全文
565 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
red-fly 2018-01-11
  • 打赏
  • 举报
回复
唉,这个问题估计我是没有机会跟了
worldy 2017-12-26
  • 打赏
  • 举报
回复
建议在使用BSTR CxxCtrl::GetLayoutList(void)返回数据后,拷贝出副本,即清除内存
red-fly 2017-12-21
  • 打赏
  • 举报
回复
昨天和今天的调试,发现了一个现象。 先说明msdn对CSing::AllocSysString()的相关解释: Commonly, if this string is passed to a COM function as an [in] parameter, then this requires the caller to free the string. This can be done by using SysFreeString, as described in the Windows SDK. For more information, see Allocating and Releasing Memory for a BSTR. 总体意思是谁调用谁释放。这样理解的话, web页面调用GetlayoutList()接口之后,应该要web自己释放。 后面测试使用如下的代码:

BSTR CxxCtrl::GetLayoutList(void)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    return theApp.m_layoutList;
}
以下4种web测试,两类两种情况。 两类是本地和服务器,即htm文件放在本地硬盘和web服务器上两种类型。 两种情况是js代码的不同写法: A. function test() { var result = GetMyOcx().GetLayoutList(); alert(result); } B. function test() { var reshaha = GetMyOcx().GetLayoutList(); alert(reshaha); } 这两种情况,只是变量名不一样 测试1: 本地+A,结果为R1 测试2: 本地+B,结果为R2 测试3: 服务器+A,结果哦R2 测试3: 服务器+B,结果哦R2 结果R1: 一切正常 结果R2: 不正常。 在调用完 GetLayoutList(void) 之后,在web页面里弹出的内容没有错,但是接下来就发生了奇怪的事情,theApp.m_layoutList 的内存地址对应的内容变化了!起初以为是js中result变量名的问题,后来换成reshaha变量名也是一样,但仅仅发生在服务器上,但如果是用result变量名,则本地和服务器都会发生此种不正常的情况。 变化后的内容大致固定,目前遇到的内容有: 1. js里的一些代码片段(不全) 2. js其他一些变量的内容(不全) 3. 网址,通常是对应的wen页面文件名,比如:http://bbs.csdn.net/mydemo.htm 出现这种情况,确定js代码里的变量是函数内的局部变量而不是全局的 这是用拼音打字累死我了,暂时只把情况说一下,以后去我电脑上再补充
zgl7903 2017-12-20
  • 打赏
  • 举报
回复
可能IE优先处理了异常, ActiveX control test Container 能模拟出异常么? 或者写一个对话框类,然后插入这个控件,单独做一个测试应用程序试试
red-fly 2017-12-20
  • 打赏
  • 举报
回复
引用 3 楼 zgl7903 的回复:
VS开启所有异常, Attach 到IE上 远程调试,找到问题点
开启所有异常没有问题,但是无法调试IE。 1. vs调试设置启动的调试程序为IE。可以启动IE,但是无法看到控件包括IE的任何打印,只能看到在启动IE时 已加载xx.dll 这样的打印行,在启动之后就没有任何其它消息了。在出现崩溃时也不能进入到“中断”状态,包括在代码中加断点都显示为无效 2. 先启动IE,再用vs attach IE,结果IE进程从任务管理器中消失,IE界面也不复存在,vs也没有进入“中断”状态,但处于调试的那种运行状态,没有断点,所以调用堆栈窗口中不会有任何信息,下断点同样无效,按F5继续运行没有任何效果,只能停止 就是没有办法直接调试IE导致不能用这种方法抓一些可能较容易的问题,郁闷
zgl7903 2017-12-20
  • 打赏
  • 举报
回复
VS开启所有异常, Attach 到IE上 远程调试,找到问题点
red-fly 2017-12-20
  • 打赏
  • 举报
回复
引用 1 楼 zgl7903 的回复:
要不试试以参数指针方式传入, 让使用者清理

BOOL GetData(BSTR *pBstr)
{
  *pBstr = SysAllocString(L"1234");
  return TRUE;
}

目前没法这样修改: 1. 控件已经发布很久了,使用者很多,如果修改,则所有用户都要修改,这个相当困难 2. 如果是vc来调用,则可以方便地清除,但如果是c#、web等调用,则如何清除? 另外,这个问题,我一直不认为问题出在这里,因为我上面的做法,我理解为最多就是内存泄露几十个字节而已,当web退出时系统回收。但是根据问题修改,似乎确实和这个地方有关,我自己没法理解这个相关的原因
zgl7903 2017-12-20
  • 打赏
  • 举报
回复
要不试试以参数指针方式传入, 让使用者清理

BOOL GetData(BSTR *pBstr)
{
  *pBstr = SysAllocString(L"1234");
  return TRUE;
}

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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