0

Я пишу программу для анализа Word-документа и экспорта данных в книгу Excel с использованием OLE Automation (как я полагаю, не-MFC). Хорошо работает в Debug, а не в Release (особенно если оптимизация включена). Ошибка в том, что IDispatch :: Invoke вызова не удалось, а именно:C++ Оптимизация, нарушающая программу OLE Automation (не-MFC)

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; 
 
}

+0

Посмотрите на область вашей переменной, которую вы ** адресуете ** ('& dispidNamed') внутри разбитого блока (подчеркивайте * внутри *). За пределами этого блока * он больше не существует *. Таким образом, вы отправляете 'dispParams' на вызов API, хорошо загруженный оборванным указателем. – WhozCraig

+0

О, ничего себе, это довольно очевидно ... как обычно, огромная трата времени на что-то немое. – donkrx

+0

Верные слова о том, что никогда не говорили о жизни инженера-программиста. Удачи. – WhozCraig

ответ

1

В этом коде:

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

dispidNamed является локальной переменной в блоке кода он находится в (то есть области, ограниченной {}).

По достижении } оно прекращает свое существование. Тогда rgdispidNamedArgs является обвисшим указателем, потому что он больше не указывает на существующую переменную.

Вам не повезло в режиме отладки, что раньше он не вызывал ошибку.