com为什么会有内存泄露啊?

时间:2023-01-11 23:16:23
IDispatch接口定义如下

HRESULT SendMessageToWindow([in] LONG lwHandle, [in] LONG lUserMsg, [in] VARIANT p1, [in] VARIANT p2, [in] VARIANT p3, [in] VARIANT p4, [in] VARIANT p5, [in] VARIANT p6, [in] VARIANT p7, [in] VARIANT p8);

//实现体
// TODO: 在此添加实现代码
if(p1.vt == VT_BSTR && p2.vt == VT_BSTR && p3.vt == VT_BSTR && p4.vt == VT_BSTR && p5.vt == VT_BSTR && p6.vt == VT_BSTR && p7.vt == VT_BSTR && p8.vt == VT_BSTR)
{
//new出来一个对象,接收消息的函数要删除这个对象,所以必须用sengmessage函数发送
ErrorItemInfo * pTempInfo = new ErrorItemInfo;
if(pTempInfo != NULL)
{
pTempInfo->RuleId = _com_util::ConvertBSTRToString(p1.bstrVal);
pTempInfo->RuleName = _com_util::ConvertBSTRToString(p2.bstrVal);
pTempInfo->RuleCheckPoint = _com_util::ConvertBSTRToString(p3.bstrVal);
pTempInfo->RuleDescription = _com_util::ConvertBSTRToString(p4.bstrVal);
pTempInfo->ErrorRange = _com_util::ConvertBSTRToString(p5.bstrVal);
pTempInfo->ErrorLine = _com_util::ConvertBSTRToString(p6.bstrVal);
pTempInfo->ErrorCount = _com_util::ConvertBSTRToString(p7.bstrVal);
pTempInfo->ObeyCount = _com_util::ConvertBSTRToString(p8.bstrVal);
pTempInfo->isRecvdFlag = false;
//把消息对象发出去
try
{
::SendMessage((HWND)lwHandle, (UINT)lUserMsg, 0, (LPARAM)pTempInfo);
}
catch(...)
{
}
int iCount = 0;
//1秒之内没有收到消息就相当于没有发送成功,清除开辟的内存
while(!(pTempInfo->isRecvdFlag) && iCount < 100)
{
Sleep(10);
iCount += 10;
}
//尝试使用::VariantClear(&p1)之类就会错误

pTempInfo->RuleId.clear();
pTempInfo->RuleName.clear();
pTempInfo->RuleCheckPoint.clear();
pTempInfo->RuleDescription.clear();
pTempInfo->ErrorRange.clear();
pTempInfo->ErrorLine.clear();
pTempInfo->ErrorCount.clear();
pTempInfo->ObeyCount.clear();
delete pTempInfo;
}
}
return S_OK;




调用


CLSID clsid;
CLSIDFromProgID(OLESTR("JsComObject.PraseCCcode"), &clsid);
CComPtr<IPraseCCcode> pIPraseCCcode;//智能指针
pIPraseCCcode.CoCreateInstance(clsid);
//准备8个参数
VARIANT v_Fl[8];
for (int ih = 0; ih < 8; ih++)
{
VariantInit(&v_Fl[ih]);
V_VT(&v_Fl[ih]) = VT_BSTR;
}
V_BSTR(&v_Fl[0]) = _com_util::ConvertStringToBSTR(mCEI.RuleId.GetBuffer());
V_BSTR(&v_Fl[1]) = _com_util::ConvertStringToBSTR(mCEI.RuleName.GetBuffer());
V_BSTR(&v_Fl[2]) = _com_util::ConvertStringToBSTR(mCEI.RuleCheckPoint.GetBuffer());
V_BSTR(&v_Fl[3]) = _com_util::ConvertStringToBSTR(mCEI.RuleDescription.GetBuffer());
V_BSTR(&v_Fl[4]) = _com_util::ConvertStringToBSTR(mCEI.ErrorRange.GetBuffer());
V_BSTR(&v_Fl[5]) = _com_util::ConvertStringToBSTR(mCEI.ErrorLine.GetBuffer());
V_BSTR(&v_Fl[6]) = _com_util::ConvertStringToBSTR(mCEI.ErrorCount.GetBuffer());
V_BSTR(&v_Fl[7]) = _com_util::ConvertStringToBSTR(mCEI.ObeyCount.GetBuffer());
//当没有这一句时,程序运行就没有泄露,只要调用就会泄露
pIPraseCCcode->SendMessageToWindow((long)h_w, (long)WM_ERRORFIND, v_Fl[0], v_Fl[1], v_Fl[2], v_Fl[3], v_Fl[4], v_Fl[5], v_Fl[6],  v_Fl[7]);
//释放8个参数
for(int ih = 0; ih < 8; ih++)
{
SysFreeString(v_Fl[ih].bstrVal);
}
pIPraseCCcode.Release();



因为pIPraseCCcode->SendMessageToWindow这函数我要调用很多次,所以泄露很严重。

6 个解决方案

#1


VariantInit对应的是VariantCleare,要成对调用。

这么费劲啊,你直接CComVariant或者CComBSTR不就可以了嘛

#2


VariantClear也泄露,是调用com后发生的,不调用那函数就没事

#3


这com是想让java调的,他不是没有sendmessage吗,我通过com让他调

#4


实验出来哦
_com_util::ConvertStringToBSTR(mCEI.RuleId.GetBuffer());保存在string中会造成字符串泄露,把指针拿来free掉就可以了

#5


你的ErrorItemInfo 是咋定义的?

MSDN:
// ConvertBSTRToString.cpp
#include <comutil.h>
#include <stdio.h>

#pragma comment(lib, "comsuppw.lib")

int main() {
   BSTR bstrText = ::SysAllocString(L"Test");
   wprintf_s(L"BSTR text: %s\n", bstrText);

   char* lpszText2 = _com_util::ConvertBSTRToString(bstrText);
   printf_s("char * text: %s\n", lpszText2);

   SysFreeString(bstrText);
   delete[] lpszText2;
}


你调用_com_util::ConvertBSTRToString(bstrText)返回值要delete[]的。


#6


VARIANT v_Fl[8];
for (int ih = 0; ih < 8; ih++)
{
    VariantInit(&v_Fl[ih]);
    V_VT(&v_Fl[ih]) = VT_BSTR;
}
。。。
for(int ih = 0; ih < 8; ih++)
{
    VariantClear(&v_Fl[ih]);
}

#1


VariantInit对应的是VariantCleare,要成对调用。

这么费劲啊,你直接CComVariant或者CComBSTR不就可以了嘛

#2


VariantClear也泄露,是调用com后发生的,不调用那函数就没事

#3


这com是想让java调的,他不是没有sendmessage吗,我通过com让他调

#4


实验出来哦
_com_util::ConvertStringToBSTR(mCEI.RuleId.GetBuffer());保存在string中会造成字符串泄露,把指针拿来free掉就可以了

#5


你的ErrorItemInfo 是咋定义的?

MSDN:
// ConvertBSTRToString.cpp
#include <comutil.h>
#include <stdio.h>

#pragma comment(lib, "comsuppw.lib")

int main() {
   BSTR bstrText = ::SysAllocString(L"Test");
   wprintf_s(L"BSTR text: %s\n", bstrText);

   char* lpszText2 = _com_util::ConvertBSTRToString(bstrText);
   printf_s("char * text: %s\n", lpszText2);

   SysFreeString(bstrText);
   delete[] lpszText2;
}


你调用_com_util::ConvertBSTRToString(bstrText)返回值要delete[]的。


#6


VARIANT v_Fl[8];
for (int ih = 0; ih < 8; ih++)
{
    VariantInit(&v_Fl[ih]);
    V_VT(&v_Fl[ih]) = VT_BSTR;
}
。。。
for(int ih = 0; ih < 8; ih++)
{
    VariantClear(&v_Fl[ih]);
}