破解OLE自动化程序(非MFC)的C++优化

问题描述:

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

0x80020004 DISP_E_PARAMNOTFOUND Parameter not found

我查*的一些建议和主要的一个似乎是未初始化的变量。这可能是怎么回事,但我仍然不明白这个具体情况。我已将其缩小到我的程序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; 
 
}

+0

看看变量的范围,你正在寻址**('&dispidNamed')块是否被破坏(强调*内的*)。在该块之外*它不再存在*。因此,您可以将'dispParams'发送到一个很好加载了悬挂指针的API调用。 – WhozCraig

+0

哦,哇,这很明显......像往常一样,在愚蠢的东西上浪费大量时间。 – donkrx

+0

从来没有谈到过软件工程师生活的真实话语。祝你好运。 – WhozCraig

在此代码:

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

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

达到}后,它不复存在。然后rgdispidNamedArgs是一个悬挂指针,因为它不再指向存在的变量。

在调试模式下,你不太幸运,它没有立即触发错误。