破解OLE自动化程序(非MFC)的C++优化
问题描述:
我正在编写一个程序来解析Word文档并将数据导出到使用OLE自动化(我猜想是非MFC方式)的Excel工作簿中。在Debug中正常工作,而不是在Release中(特别是如果启用了优化)。该错误是的IDispatch :: Invoke调用失败,具体如下:破解OLE自动化程序(非MFC)的C++优化
0x80020004 DISP_E_PARAMNOTFOUND Parameter not found
我查StackOverflow的一些建议和主要的一个似乎是未初始化的变量。这可能是怎么回事,但我仍然不明白这个具体情况。我已将其缩小到我的程序Automation::Dispatch::Invoke
中的一个函数,该函数最后致电IDispatch::Invoke
。传递到Automation::Dispatch::Invoke
的参数是正确的,所以问题出现在代码中。
查看我改编的基本代码(来自MSDN),我能够得到它的工作和缩小确切的问题线。下面显示的代码不起作用,但注释表明我为了使其工作而移动的那一行(查找2条注释为<--- Problem line
的注释)。在调试模式下,这一行的位置并不重要,它在任何一个地方都可以工作。
我的问题是什么修复,为什么它是一个问题开始?谢谢,让我知道我是否可以让问题更清楚。
HRESULT Automation::Dispatch::Invoke(int cmd, std::string name, std::vector<VARIANT> values)
{
USES_CONVERSION;
HRESULT result;
/* Get DISPID for name passed */
DISPID dispID;
LPOLESTR nameOle=A2OLE(name.c_str());
result=pObjectInt->GetIDsOfNames(IID_NULL, &nameOle, 1, LOCALE_USER_DEFAULT, &dispID);
if (FAILED(result)) {
return result;
}
/* Reverse elements in values vector so they are invoked in the correct order */
std::reverse(values.begin(), values.end());
/* Allocate memory for object values */
VARIANT *pValues=new VARIANT[values.size() + 1];
for (unsigned int i=0; i < values.size(); ++i) {
pValues[i]=values[i];
}
/* Build DISPPARAMS */
DISPPARAMS dispParams= {NULL, NULL, 0, 0};
/* DISPID dispidNamed=DISPID_PROPERTYPUT; <--- PROBLEM LINE moved here makes it work */
dispParams.cArgs=values.size();
dispParams.rgvarg=pValues;
/* Handle special-case for property-puts */
if (cmd==DISPATCH_PROPERTYPUT) {
DISPID dispidNamed=DISPID_PROPERTYPUT; /* <--- PROBLEM LINE here */
dispParams.cNamedArgs=1;
dispParams.rgdispidNamedArgs=&dispidNamed;
}
/* Make the call */
if (cmd==DISPATCH_METHOD || cmd==DISPATCH_PROPERTYPUT) {
result=pObjectInt->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, cmd, &dispParams, NULL, NULL, NULL);
}
else {
VariantInit(&objectData);
result=pObjectInt->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, cmd, &dispParams, &objectData, NULL, NULL);
}
delete[] pValues;
return result;
}
答
在此代码:
if (cmd==DISPATCH_PROPERTYPUT) {
DISPID dispidNamed=DISPID_PROPERTYPUT; /* <--- PROBLEM LINE here */
dispParams.cNamedArgs=1;
dispParams.rgdispidNamedArgs=&dispidNamed;
}
dispidNamed
是一个局部变量的代码块它是在(由{
}
分隔即区域)。
达到}
后,它不复存在。然后rgdispidNamedArgs
是一个悬挂指针,因为它不再指向存在的变量。
在调试模式下,你不太幸运,它没有立即触发错误。
看看变量的范围,你正在寻址**('&dispidNamed')块是否被破坏(强调*内的*)。在该块之外*它不再存在*。因此,您可以将'dispParams'发送到一个很好加载了悬挂指针的API调用。 – WhozCraig
哦,哇,这很明显......像往常一样,在愚蠢的东西上浪费大量时间。 – donkrx
从来没有谈到过软件工程师生活的真实话语。祝你好运。 – WhozCraig