I am struggling with intermittent application crashes in C ++. I am not a C ++ programmer, but I am entrusted with solving this problem, so I really hope that you can help me.
Often the application runs fine, and then sometimes the crash is ruled out.
When you enter debugging from running exe, the line of code seems to be to blame - see the first screenshot.
I added some locales in the second screenshot.
This line of code calls the 'ClearVariant' function, which for this function looks like this:
void CXLAutomation::ClearVariant(VARIANTARG *pvarg)
{
pvarg->vt = VT_EMPTY;
pvarg->wReserved1 = 0;
pvarg->wReserved2 = 0;
pvarg->wReserved3 = 0;
pvarg->lVal = 0;
}
The entire cpp file is at the end of the message. OpenExcelFile is the feature that leads to this problem - as soon as possible from the call stack in screenshots.


static char THIS_FILE[]=__FILE__;
CXLAutomation::CXLAutomation()
{
m_pdispExcelApp = NULL;
m_pdispWorkbook = NULL;
m_pdispWorksheet = NULL;
m_pdispActiveChart = NULL;
InitOLE();
StartExcel();
}
CXLAutomation::CXLAutomation(BOOL bVisible)
{
m_pdispExcelApp = NULL;
m_pdispWorkbook = NULL;
m_pdispWorksheet = NULL;
m_pdispActiveChart = NULL;
InitOLE();
StartExcel();
SetExcelVisible(bVisible);
CreateWorkSheet();
}
CXLAutomation::~CXLAutomation()
{
ReleaseDispatch();
OleUninitialize();
}
BOOL CXLAutomation::InitOLE()
{
DWORD dwOleVer;
dwOleVer = CoBuildVersion();
if (rmm != HIWORD(dwOleVer))
{
MessageBox(NULL, _T("Incorrect version of OLE libraries."), "Failed", MB_OK | MB_ICONSTOP);
return FALSE;
}
if (FAILED(OleInitialize(NULL)))
{
MessageBox(NULL, _T("Cannot initialize OLE."), "Failed", MB_OK | MB_ICONSTOP);
return FALSE;
}
return TRUE;
}
BOOL CXLAutomation::StartExcel()
{
CLSID clsExcelApp;
if (m_pdispExcelApp != NULL)
return TRUE;
if (FAILED(CLSIDFromProgID(L"Excel.Application", &clsExcelApp)))
{
MessageBox(NULL, _T("Cannot obtain CLSID from ProgID"), "Failed", MB_OK | MB_ICONSTOP);
return FALSE;
}
if (FAILED(CoCreateInstance(clsExcelApp, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&m_pdispExcelApp)))
{
MessageBox(NULL, _T("Cannot start an instance of Excel for Automation."), "Failed", MB_OK | MB_ICONSTOP);
return FALSE;
}
return TRUE;
}
BOOL CXLAutomation::ExlInvoke(IDispatch *pdisp, LPOLESTR szMember, VARIANTARG * pvargReturn,
WORD wInvokeAction, WORD wFlags)
{
HRESULT hr;
DISPPARAMS dispparams;
unsigned int uiArgErr;
EXCEPINFO excep;
m_alpszArgNames[0] = szMember;
hr = pdisp->GetIDsOfNames( IID_NULL, m_alpszArgNames,
1 + m_iNamedArgCount, LOCALE_SYSTEM_DEFAULT, m_aDispIds);
if (FAILED(hr))
{
if (!(wFlags & DISP_NOSHOWEXCEPTIONS))
ShowException(szMember, hr, NULL, 0);
return FALSE;
}
if (pvargReturn != NULL)
ClearVariant(pvargReturn);
if (wInvokeAction & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
{
m_iNamedArgCount = 1;
m_aDispIds[1] = DISPID_PROPERTYPUT;
pvargReturn = NULL;
}
dispparams.rgdispidNamedArgs = m_aDispIds + 1;
dispparams.rgvarg = m_aVargs;
dispparams.cArgs = m_iArgCount;
dispparams.cNamedArgs = m_iNamedArgCount;
excep.pfnDeferredFillIn = NULL;
hr = pdisp->Invoke(m_aDispIds[0], IID_NULL, LOCALE_SYSTEM_DEFAULT,
wInvokeAction, &dispparams, pvargReturn, &excep, &uiArgErr);
if (wFlags & DISP_FREEARGS)
ClearAllArgs();
if (FAILED(hr))
{
if (!(wFlags & DISP_NOSHOWEXCEPTIONS))
ShowException(szMember, hr, &excep, uiArgErr);
SysFreeString(excep.bstrSource);
SysFreeString(excep.bstrDescription);
SysFreeString(excep.bstrHelpFile);
return FALSE;
}
return TRUE;
}
void CXLAutomation::ClearVariant(VARIANTARG *pvarg)
{
pvarg->vt = VT_EMPTY;
pvarg->wReserved1 = 0;
pvarg->wReserved2 = 0;
pvarg->wReserved3 = 0;
pvarg->lVal = 0;
}
void CXLAutomation::ClearAllArgs()
{
int i;
for (i = 0; i < m_iArgCount; i++)
{
if (m_awFlags[i] & DISPARG_NOFREEVARIANT)
ClearVariant(&m_aVargs[i]);
else
ReleaseVariant(&m_aVargs[i]);
}
m_iArgCount = 0;
m_iNamedArgCount = 0;
}
void CXLAutomation::ReleaseVariant(VARIANTARG *pvarg)
{
VARTYPE vt;
VARIANTARG *pvargArray;
long lLBound, lUBound, l;
vt = pvarg->vt & 0xfff;
if (V_ISARRAY(pvarg))
{
if (vt == VT_VARIANT)
{
SafeArrayGetLBound(pvarg->parray, 1, &lLBound);
SafeArrayGetUBound(pvarg->parray, 1, &lUBound);
if (lUBound > lLBound)
{
lUBound -= lLBound;
SafeArrayAccessData(pvarg->parray, (void**)&pvargArray);
for (l = 0; l < lUBound; l++)
{
ReleaseVariant(pvargArray);
pvargArray++;
}
SafeArrayUnaccessData(pvarg->parray);
}
}
else
{
return ;
}
SafeArrayDestroy(pvarg->parray);
}
else
{
switch (vt)
{
case VT_DISPATCH:
pvarg->pdispVal->Release();
break;
case VT_BSTR:
SysFreeString(pvarg->bstrVal);
break;
case VT_I2:
case VT_BOOL:
case VT_R8:
case VT_ERROR:
break;
default:
return;
break;
}
}
ClearVariant(pvarg);
return ;
}
BOOL CXLAutomation::SetExcelVisible(BOOL bVisible)
{
if (m_pdispExcelApp == NULL)
return FALSE;
ClearAllArgs();
AddArgumentBool(NULL, 0, bVisible);
return ExlInvoke(m_pdispExcelApp, L"Visible", NULL, DISPATCH_PROPERTYPUT, DISP_FREEARGS);
}
BOOL CXLAutomation::SetExcelFileValidation(BOOL bFileValidation)
{
if (m_pdispExcelApp == NULL)
return FALSE;
ClearAllArgs();
AddArgumentBool(NULL, 0, bFileValidation);
return ExlInvoke(m_pdispExcelApp, L"FileValidation", NULL, DISPATCH_PROPERTYPUT, DISP_FREEARGS);
}
void CXLAutomation::AddArgumentCommon(LPOLESTR lpszArgName, WORD wFlags, VARTYPE vt)
{
ClearVariant(&m_aVargs[m_iArgCount]);
m_aVargs[m_iArgCount].vt = vt;
m_awFlags[m_iArgCount] = wFlags;
if (lpszArgName != NULL)
{
m_alpszArgNames[m_iNamedArgCount + 1] = lpszArgName;
m_iNamedArgCount++;
}
}
BOOL CXLAutomation::AddArgumentDispatch(LPOLESTR lpszArgName, WORD wFlags, IDispatch * pdisp)
{
AddArgumentCommon(lpszArgName, wFlags, VT_DISPATCH);
m_aVargs[m_iArgCount++].pdispVal = pdisp;
return TRUE;
}
BOOL CXLAutomation::AddArgumentInt2(LPOLESTR lpszArgName, WORD wFlags, int i)
{
AddArgumentCommon(lpszArgName, wFlags, VT_I2);
m_aVargs[m_iArgCount++].iVal = i;
return TRUE;
}
BOOL CXLAutomation::AddArgumentBool(LPOLESTR lpszArgName, WORD wFlags, BOOL b)
{
AddArgumentCommon(lpszArgName, wFlags, VT_BOOL);
m_aVargs[m_iArgCount++].boolVal = b ? -1 : 0;
return TRUE;
}
BOOL CXLAutomation::AddArgumentDouble(LPOLESTR lpszArgName, WORD wFlags, double d)
{
AddArgumentCommon(lpszArgName, wFlags, VT_R8);
m_aVargs[m_iArgCount++].dblVal = d;
return TRUE;
}
BOOL CXLAutomation::ReleaseExcel()
{
if (m_pdispExcelApp == NULL)
return TRUE;
ClearAllArgs();
ExlInvoke(m_pdispExcelApp, L"Quit", NULL, DISPATCH_METHOD, 0);
ReleaseDispatch();
return TRUE;
}
BOOL CXLAutomation::CreateWorkSheet()
{
if(NULL == m_pdispExcelApp)
return FALSE;
BOOL fResult;
VARIANTARG varg1, varg2;
IDispatch *pdispRange = NULL;
IDispatch *pdispActiveSheet = NULL;
IDispatch *pdispActiveCell = NULL;
IDispatch *pdispCrt = NULL;
ClearAllArgs();
if (!ExlInvoke(m_pdispExcelApp, L"Workbooks", &varg1, DISPATCH_PROPERTYGET, 0))
return FALSE;
ClearAllArgs();
AddArgumentInt2(L"Template", 0, xlWorksheet);
fResult = ExlInvoke(varg1.pdispVal, L"Add", &varg2, DISPATCH_METHOD, 0);
ReleaseVariant(&varg1);
if (!fResult)
return FALSE;
m_pdispWorkbook = varg2.pdispVal;
ClearAllArgs();
AddArgumentInt2(NULL, 0, 1);
if (!ExlInvoke(m_pdispWorkbook, L"Worksheets", &varg2, DISPATCH_PROPERTYGET, 0))
goto CreateWsBail;
m_pdispWorksheet = varg2.pdispVal;
fResult = TRUE;
CreateWsExit:
if (pdispRange != NULL)
pdispRange->Release();
if (pdispCrt != NULL)
pdispCrt->Release();
return fResult;
CreateWsBail:
fResult = FALSE;
goto CreateWsExit;
}
BOOL CXLAutomation::AddArgumentOLEString(LPOLESTR lpszArgName, WORD wFlags, LPOLESTR lpsz)
{
BSTR b;
b = SysAllocString(lpsz);
if (!b)
return FALSE;
AddArgumentCommon(lpszArgName, wFlags, VT_BSTR);
m_aVargs[m_iArgCount++].bstrVal = b;
return TRUE;
}
BOOL CXLAutomation::AddArgumentCString(LPOLESTR lpszArgName, WORD wFlags, CString szStr)
{
BSTR b;
b = szStr.AllocSysString();
if (!b)
return FALSE;
AddArgumentCommon(lpszArgName, wFlags, VT_BSTR);
m_aVargs[m_iArgCount++].bstrVal = b;
return TRUE;
}
BOOL CXLAutomation::AddArgumentCStringArray(LPOLESTR lpszArgName, WORD wFlags, LPOLESTR *paszStrings, int iCount)
{
SAFEARRAY *psa;
SAFEARRAYBOUND saBound;
VARIANTARG *pvargBase;
VARIANTARG *pvarg;
int i, j;
saBound.lLbound = 0;
saBound.cElements = iCount;
psa = SafeArrayCreate(VT_VARIANT, 1, &saBound);
if (psa == NULL)
return FALSE;
SafeArrayAccessData(psa, (void**) &pvargBase);
pvarg = pvargBase;
for (i = 0; i < iCount; i++)
{
ClearVariant(pvarg);
pvarg->vt = VT_BSTR;
if ((pvarg->bstrVal = SysAllocString(*paszStrings++)) == NULL)
{
pvarg = pvargBase;
for (j = 0; j < i; j++)
{
SysFreeString(pvarg->bstrVal);
pvarg++;
}
SafeArrayDestroy(psa);
return FALSE;
}
pvarg++;
}
SafeArrayUnaccessData(psa);
AddArgumentCommon(lpszArgName, wFlags, VT_VARIANT | VT_ARRAY);
m_aVargs[m_iArgCount++].parray = psa;
return TRUE;
}
void CXLAutomation::ReleaseDispatch()
{
if(NULL != m_pdispExcelApp)
{
m_pdispExcelApp->Release();
m_pdispExcelApp = NULL;
}
if(NULL != m_pdispWorksheet)
{
m_pdispWorksheet->Release();
m_pdispWorksheet = NULL;
}
if(NULL != m_pdispWorkbook)
{
m_pdispWorkbook->Release();
m_pdispWorkbook = NULL;
}
if(NULL != m_pdispActiveChart)
{
m_pdispActiveChart->Release();
m_pdispActiveChart = NULL;
}
}
void CXLAutomation::ShowException(LPOLESTR szMember, HRESULT hr, EXCEPINFO *pexcep, unsigned int uiArgErr)
{
TCHAR szBuf[512];
switch (GetScode(hr))
{
case DISP_E_UNKNOWNNAME:
wsprintf(szBuf, "%s: Unknown name or named argument.", szMember);
break;
case DISP_E_BADPARAMCOUNT:
wsprintf(szBuf, "%s: Incorrect number of arguments.", szMember);
break;
case DISP_E_EXCEPTION:
wsprintf(szBuf, "%s: Error %d: ", szMember, pexcep->wCode);
if (pexcep->bstrDescription != NULL)
lstrcat(szBuf, (char*)pexcep->bstrDescription);
else
lstrcat(szBuf, "<<No Description>>");
break;
case DISP_E_MEMBERNOTFOUND:
wsprintf(szBuf, "%s: method or property not found.", szMember);
break;
case DISP_E_OVERFLOW:
wsprintf(szBuf, "%s: Overflow while coercing argument values.", szMember);
break;
case DISP_E_NONAMEDARGS:
wsprintf(szBuf, "%s: Object implementation does not support named arguments.",
szMember);
break;
case DISP_E_UNKNOWNLCID:
wsprintf(szBuf, "%s: The locale ID is unknown.", szMember);
break;
case DISP_E_PARAMNOTOPTIONAL:
wsprintf(szBuf, "%s: Missing a required parameter.", szMember);
break;
case DISP_E_PARAMNOTFOUND:
wsprintf(szBuf, "%s: Argument not found, argument %d.", szMember, uiArgErr);
break;
case DISP_E_TYPEMISMATCH:
wsprintf(szBuf, "%s: Type mismatch, argument %d.", szMember, uiArgErr);
break;
default:
wsprintf(szBuf, "%s: Unknown error occured.", szMember);
break;
}
MessageBox(NULL, szBuf, "OLE Error", MB_OK | MB_ICONSTOP);
}
BOOL CXLAutomation::OpenExcelFile(CString szFileName)
{
if(NULL == m_pdispExcelApp)
return FALSE;
if(szFileName.IsEmpty())
return FALSE;
VARIANTARG varg1, vargWorkbook, vargWorksheet;
SetExcelFileValidation(FALSE);
ClearAllArgs();
if (!ExlInvoke(m_pdispExcelApp, L"Workbooks", &varg1, DISPATCH_PROPERTYGET, 0))
return FALSE;
ClearAllArgs();
AddArgumentCString(L"Filename", 0, szFileName);
if (!ExlInvoke(varg1.pdispVal, L"Open", &vargWorkbook, DISPATCH_PROPERTYGET, DISP_FREEARGS))
return FALSE;
ClearAllArgs();
AddArgumentInt2(NULL, 0, 1);
if (!ExlInvoke(vargWorkbook.pdispVal, L"Worksheets", &vargWorksheet, DISPATCH_PROPERTYGET, DISP_FREEARGS))
return FALSE;
ClearAllArgs();
SetExcelVisible(TRUE);
m_pdispWorkbook = vargWorkbook.pdispVal;
m_pdispWorksheet = vargWorksheet.pdispVal;
ReleaseDispatch();
return TRUE;
}