C++ 优化破坏 OLE 自动化程序(非 MFC)
C++ Optimization breaking OLE Automation program (non-MFC)
我正在编写一个程序来解析 Word 文档并使用 OLE 自动化(我猜是非 MFC 方式)将数据导出到 Excel 工作簿。在 Debug 中工作正常,在 Release 中不是这样(特别是如果启用了优化)。报错是IDispatch::Invoke调用失败,具体是:
0x80020004 DISP_E_PARAMNOTFOUND Parameter not found
我检查了 Whosebug 的一些建议,主要的似乎是未初始化的变量。这可能是正在发生的事情,但我仍然不明白这个具体案例。我已经将它缩小到我的程序 Automation::Dispatch::Invoke
中的一个函数,它负责最终调用 IDispatch::Invoke
。传递给 Automation::Dispatch::Invoke
的参数是正确的,因此问题出在它的代码中。
查看我从中改编的基本代码(来自 MSDN),我能够让它工作并缩小确切的问题范围。下面显示了不起作用的代码,但注释指出了我为使其正常工作而移动的行(查找带有 <--- Problem line
注释的 2 行)。在调试模式下,这条线的位置无关紧要,它在任何一个地方都有效。
我的问题是这能解决什么问题,为什么从一开始就是个问题?谢谢,让我知道是否可以使问题更清楚。
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
就是一个悬垂指针,因为它不再指向一个已经存在的变量。
你在调试模式下很不走运,它没有尽快触发错误。
我正在编写一个程序来解析 Word 文档并使用 OLE 自动化(我猜是非 MFC 方式)将数据导出到 Excel 工作簿。在 Debug 中工作正常,在 Release 中不是这样(特别是如果启用了优化)。报错是IDispatch::Invoke调用失败,具体是:
0x80020004 DISP_E_PARAMNOTFOUND Parameter not found
我检查了 Whosebug 的一些建议,主要的似乎是未初始化的变量。这可能是正在发生的事情,但我仍然不明白这个具体案例。我已经将它缩小到我的程序 Automation::Dispatch::Invoke
中的一个函数,它负责最终调用 IDispatch::Invoke
。传递给 Automation::Dispatch::Invoke
的参数是正确的,因此问题出在它的代码中。
查看我从中改编的基本代码(来自 MSDN),我能够让它工作并缩小确切的问题范围。下面显示了不起作用的代码,但注释指出了我为使其正常工作而移动的行(查找带有 <--- Problem line
注释的 2 行)。在调试模式下,这条线的位置无关紧要,它在任何一个地方都有效。
我的问题是这能解决什么问题,为什么从一开始就是个问题?谢谢,让我知道是否可以使问题更清楚。
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
就是一个悬垂指针,因为它不再指向一个已经存在的变量。
你在调试模式下很不走运,它没有尽快触发错误。