Member 13261094 Ответов: 1

Повреждение памяти(исключение read access violation 0x3e8.) после динамической загрузки в C++ с использованием VS2017


Приведенный ниже код прекрасно работает в VS2010 . Но это не работает в VS2017. Ниже фрагмент кода .

void ResultRule::ExecuteFireRule()
{
	HINSTANCE         hModule;
	CSiRuleReturn *pRuleRet = NULL;

	FIRERULE pFunc;

	hModule = LoadLibrary("siJCLJOb.dll");
	
	pFunc = (FIRERULE) GetProcAddress(hModule, "FireRule");

	if (pFunc != NULL)
	{		
		try {
			pRuleRet = pFunc(inputList);
		}
		catch (CException *)
		{
			DeleteModuleInputList(inputList);
			throw;
		}
		DeleteModuleInputList(inputList);

		if (pRuleRet->GetReturnCode() > retVal.GetReturnCode())
		{
			retVal.SetReturnCode(pRuleRet->GetReturnCode());
		}
		if (pRuleRet->GetReturnObject())
		{
			retVal.SetReturnObject(pRuleRet->GetReturnObject());
		}
		retVal.AppendErrors(pRuleRet->GetErrorList());
		delete pRuleRet;		
	}
	else
	{
		CString msg;
		msg.Format("The result rule defined on line %d of %s referenced result module [%s], which has no exported FireRules function.", m_fileLineNumber, m_ruleFile, m_moduleName);
		CSiException *pEx = new CSiException("CSiResultRule::FireRule", msg);
		throw pEx;
	}
}


------------------------------------------------------------------------------
Calling Above code:
//Calling above ExecuteFireRule(), which will dynamically load firerule function of siJCLJOb.dll.

CSiRuleReturn ruleRet = iRulesProcessor::GetInstance()->FireRequestRule("JCLCARD", NULL, "");
CString *pJobTemplate = (CString*)ruleRet.GetReturnObject(); // gives me the correct values after executing FireRule function of siJCLJob.dll

CLauncherApp* Obj = (CLauncherApp*)AfxGetApp(); // after dynmic execution , it corrupts the memory /main thread . it show me the object siJCLJob.dll, when i place my cursor to Obj


Что я уже пробовал:

Мы сталкиваемся с одной и той же проблемой во всех динамических загруженных объектах MFC. Мы попытались скомпилировать код, добавив
/Zc:threadSafeInit 
... но получение ошибки во время выполнения
Exception thrown: read access violation.
this was 0x3E8.

Rick York

Я предполагаю, что у вас есть проблема несоответствия версий с библиотеками DLL MFC. Попробуйте перестроить библиотеки DLL. Если вы не можете этого сделать, то вам, вероятно, нужно остаться с VS2010.

Member 13261094

Все MFC и DLL компилируются с использованием VS2017 в режиме отладки.

KarstenK

Рик прав, лучше всего построить все dll с одной и той же версией VS. Другой способ-сделать статическую сборку.

Shao Voon Wong

Проверьте, являются ли hModule и pFunc нулевыми. Проверка siJCLJOb.dll находится в исполняемом пути. Если они верны, то это может быть среда выполнения VC для siJCLJOb.dll не найден/не установлен. Попробуйте установить VS2010 runtime.

Member 13261094

Я отладил код, и он загружается в систему. siJCLJOB.dll и pFunc не является нулевым. После выполнения siJCLJOB.dll функция, она развращает основную память/поток.

Shao Voon Wong

Возможно, FireRule() и его указатель на функцию, объявление FIRERULE не совпадают? Пожалуйста, покажите 2 декларации.

Member 13261094

FireRule() работает нормально... Он выполняет код, написанный в SiJCLJob.dll и верните мне правильное значение в строке . но после этого код не работает ... он обнуляет основной поток.

siRuleReturn* FireRule(CObList& list)// в SiJCJoB

Shao Voon Wong

Объявление функции должно быть

siRuleReturn* по WinAPI FireRule(содержащий coblist&усилитель; список);

И объявление указателя функции должно быть

siRuleReturn* (WINAPI* FIRERULE)(CObList& list);

В прошлом я сталкивался с кодом, работавшим в более старом VC++, но разбившимся в более новом VC++. Оказывается, ошибка находится в нашем коде, потому что функция обратилась к элементу после конца вектора. Он не разбился в старом VC++, потому что в конце вектора нет ничего, что можно было бы испортить. Code-review код FireRule является правильным и не имеет доступа за пределы.

1 Ответов

Рейтинг:
0

Michael Haephrati

Когда вы используете

hModule = LoadLibrary("siJCLJOb.dll");

pFunc = (FIRERULE) GetProcAddress(hModule, "FireRule");


Существует вариант, что LoadLibrary потерпит неудачу, и если это произойдет, то следующая строка вызовет нарушение доступа.

Измените его на:

hModule = LoadLibrary("siJCLJOb.dll");

if(hModule) pFunc = (FIRERULE) GetProcAddress(hModule, "FireRule");