我的程序加载了几个dll并调用它们的函数。dlls可以使用不同版本的CRT。
当C运行时检查参数的有效性并发现问题时,它会调用无效的参数句柄,这反过来会关闭应用程序,不管是否使用“发送-不发送”对话框。
我试着调用*_set_invalid_parameter_handler*,但是只有在从坏的dll中调用它时,它才能工作。我尝试了SetErrorMode,但是我所做的就是在没有对话框的情况下杀死进程。
有什么办法处理这些例外吗?我不在乎某些资源是否受到损害。我只想让用户保存配置。如果出现该对话框,则他们单击它并终止该进程。
编辑原来是加载所有版本的或枚举所有all失败的解决方案。为了说明这一点,下面是一个小例子:
这将是我的主要应用程序(让我们调用文件应用程序。c):
#include <windows.h>
void myInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved) {
wprintf(L"Invalid parameter detected in function %s. File: %s Line: %d\n", function, file, line);
wprintf(L"Expression: %s\n", expression);
}
void fixMyProblem() {
}
int main(int argc, char **argv) {
HMODULE hModule = LoadLibrary("extension.dll");
void (WINAPI *function)() = GetProcAddress(hModule, "function");
fixMyProblem();
function();
}这个应用程序加载一个做坏事的dll (它不是由我开发的,所以我不会接受任何告诉我修复错误的解决方案)。让我们调用那个文件扩展名.c。
#include <stdio.h>
__declspec(dllexport) void function() {
printf("do bad stuff");
fopen(NULL, "r");
}要编译,请做:
cl extension.c /link /OUT:extension.dll /DLL
cl application.c问题是在函数fixMyProblem()中做什么,这样就不会在XP上得到发送/不发送对话框,或者应用程序在7上停止工作对话框。
根据大卫·格拉德费尔特的说法我应该这么做
void fixMyProblem() {
_set_invalid_parameter_handler(myInvalidParameterHandler);
}也可以为每个版本的 CRT执行此操作。事实证明,即使只有一个版本的CRT (我对exe和dll都使用相同的版本),它仍然不能工作。它们都使用相同版本的,但似乎它们不使用相同的 CRT。
如果是这样的话,我假设我必须更改的内容在DLL中。当然,它不导出*_set_invalid_parameter_handler*。
但公平地说,大卫·赫弗南的解决方案如下:
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")
void fixMyProblem() {
HANDLE hProcess = GetCurrentProcess();
HMODULE *hModules;
DWORD requiredSize = 0;
DWORD secondRequiredSize = 0;
if (!EnumProcessModules(hProcess, NULL, 0, &requiredSize)) {
printf("oops\n");
return;
}
hModules = malloc(requiredSize);
if (EnumProcessModules(hProcess, hModules, requiredSize, &secondRequiredSize)) {
int i;
int loadedModules = min(requiredSize, secondRequiredSize) / sizeof(HMODULE);
for (i = 0; i < loadedModules; i++) {
void *(WINAPI *_set_invalid_parameter_handler_function)(void *) = (void *(WINAPI *)(void *)) GetProcAddress(hModules[i], "_set_invalid_parameter_handler");
if (_set_invalid_parameter_handler_function != NULL) {
_set_invalid_parameter_handler_function(myInvalidParameterHandler);
printf("fixed dll %d\n", i);
}
}
} else {
printf("oops\n");
}
free(hModules);
}对于我的实际应用程序,而不是这个测试,我修复了一个dll (msvcp90.dll)。它仍然不能解决我的问题。
如果能帮忙解决这个问题,我将不胜感激。
发布于 2012-11-16 11:13:38
如果dll是用静态链接的CRT构建的,则CRT的状态和函数将是dll实例的本地。我假设CRT使用的无效参数处理程序正在从操作系统调用UnhandledExceptionFilter函数,以显示“很好”的错误对话框。
您可以尝试连接像UnhandledExceptionFilter或TerminateProcess这样的函数,让dll使用您自己的函数。您可以通过解析加载dll的Import表,搜索您感兴趣的函数名,并将地址更改为指向您的函数来实现这一点。
发布于 2011-06-21 20:51:33
您可以始终枚举流程中的模块,如果是C运行时,则通过调用GetProcAddress来获取无效的参数处理程序。
但你最好试着从根本上解决问题。试图忽略这些问题通常只会导致更多的问题,因为内存会被破坏等等。
发布于 2011-06-21 20:41:49
您可以创建另一个DLL,该DLL使用与DLL使用的版本相同的CRT版本,该版本会导致调用无效的参数处理程序,并在该新DLL中注册无效的参数处理程序。无效的参数处理程序对于进程/CRT版本组合是全局的。
如果您不知道DLL使用的是哪个版本,并且无法确定它,最糟糕的情况是您创建了几个DLL,每个CRT版本一个:
static/dynamic/multithreaded/single-threaded
您可能会将它们创建为静态.lib文件,并将它们链接到一个(非常混乱的) DLL中。
https://stackoverflow.com/questions/6113898
复制相似问题