C ++ Оптимизация, ломающая программу автоматизации OLE (не MFC)

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

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

Решение

В этом коде:

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

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

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

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

1

Другие решения


По вопросам рекламы [email protected]