【问题标题】:C++ Optimization breaking OLE Automation program (non-MFC)C++ 优化破坏 OLE 自动化程序(非 MFC)
【发布时间】:2015-06-03 07:10:37
【问题描述】:

我正在编写一个程序来解析 Word 文档并使用 OLE 自动化(我猜是非 MFC 方式)将数据导出到 Excel 工作簿。在 Debug 中工作正常,在 Release 中则不然(特别是在启用优化的情况下)。错误是IDispatch::Invoke调用失败,具体是:

0x80020004 DISP_E_PARAMNOTFOUND Parameter not found

我检查了 StackOverflow 的一些建议,主要的似乎是未初始化的变量。这可能是正在发生的事情,但我仍然不明白这个具体案例。我已将其缩小到我的程序Automation::Dispatch::Invoke 中的一个函数,它负责最终调用IDispatch::Invoke。传递给Automation::Dispatch::Invoke 的参数是正确的,所以问题出在它的代码中。

查看我改编的基本代码(来自 MSDN),我能够让它工作并缩小确切的问题范围。下面显示了不起作用的代码,但 cmets 表示我移动以使其正常工作的行(查找带有 <--- 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;
}

【问题讨论】:

  • 查看你在被破坏的块中寻址 (&amp;dispidNamed) 的变量的范围(强调within)。在该块之外它不再存在。因此,您将 dispParams 发送到一个很好地加载了一个悬空指针的 API 调用。
  • 哦,哇,这很明显......像往常一样,在愚蠢的事情上浪费了大量时间。
  • 更真实的说法是从未有人说过软件工程师的生活。祝你好运。

标签: c++ optimization visual-studio-2013 ole office-automation


【解决方案1】:

在这段代码中:

if (cmd==DISPATCH_PROPERTYPUT) {
    DISPID dispidNamed=DISPID_PROPERTYPUT;   /* <--- PROBLEM LINE here */
    dispParams.cNamedArgs=1;
    dispParams.rgdispidNamedArgs=&dispidNamed;
}

dispidNamed 是它所在代码块的局部变量(即由{} 分隔的区域)。

到达} 后,它就不再存在。那么rgdispidNamedArgs 是一个悬空指针,因为它不再指向一个存在的变量。

你在调试模式下很不走运,它没有尽快触发错误。

【讨论】:

    猜你喜欢
    • 2021-07-14
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    相关资源
    最近更新 更多