【发布时间】:2013-06-28 15:11:38
【问题描述】:
以下代码在 VS2012 中按预期工作,调试版本:
#include <SDKDDKVer.h>
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <io.h>
#include <assert.h>
DWORD WINAPI childThread(LPVOID param) {
printf("I'm the child!\n"); fflush(stdout);
_isatty(-1);
//assert(1==0);
return 0;
}
void myInvalidParameterHandler(const wchar_t * expression, const wchar_t * function, const wchar_t * file, unsigned int line, uintptr_t pReserved) {
wprintf(L"%s:%i %s() - Invalid parameter [%s]", file, line, function, expression);
}
int _tmain(int argc, _TCHAR* argv[]) {
wprintf(L"Registering invalid parameter handler\n");
_invalid_parameter_handler newHandler = myInvalidParameterHandler;
_set_invalid_parameter_handler(newHandler);
printf("Testing.\n");
CreateThread(NULL, 0, childThread, NULL, 0, NULL);
// CreateThread(NULL, 0, childThread, NULL, 0, NULL);
printf("Thread(s) created, press Enter to exit.\n");
getchar();
return 0;
}
参数验证将导致子线程的_isatty(-1) 弹出“Abort/Retry/Ignore”,并在必要时一直存在。如果我点击“Ignore”,则调用 myInvalidParameterHandler,程序运行直到我点击 Enter。都很好。
如果第二个CreateThread 未注释,因此同时发生两个参数验证失败,则程序静默退出。有时会弹出 Abort/Retry/Ignore,但它会在一秒钟内消失。该程序永远不会因为 main 的 getchar 而挂起。
从调试器中运行时,它会在以下位置遇到断点:
msvcr110d.dll!_CrtDbgBreak() Line 87 C
msvcr110d.dll!_VCrtDbgReportW(int nRptType, void * returnAddress, const wchar_t * szFile, int nLine, const wchar_t * szModule, const wchar_t * szFormat, char * arglist) Line 506 C
msvcr110d.dll!_CrtDbgReportWV(int nRptType, void * returnAddress, const wchar_t * szFile, int nLine, const wchar_t * szModule, const wchar_t * szFormat, char * arglist) Line 262 C++
msvcr110d.dll!_CrtDbgReportW(int nRptType, const wchar_t * szFile, int nLine, const wchar_t * szModule, const wchar_t * szFormat, ...) Line 279 C++
msvcr110d.dll!_isatty(int fh) Line 41 C
assertTest.exe!childThread(void * param) Line 10 C++
这不是同时断言的一般问题。如果我交换_isatty(-1) 和assert(1==0) 的评论,那么它会达到我的预期。我们得到了两个 abort/retry/ignore 弹出窗口,它们一直在徘徊,然后主线程运行到完成。
发布版本没有这个问题,无效的参数处理程序被两个线程调用并且执行总是继续。
就上下文而言,我们有一个长时间运行的服务器进程,它在多个线程中达到_isatty(-1) 并静默退出。这是一个我们已经解决的问题,但这种行为使追踪变得非常困难。我想知道是否有什么可以提供帮助的。
我看到了question with similar behavior,但那是 MinGW 并且被确定为编译器错误。我已经验证测试在 VS2012 中有效。
【问题讨论】:
-
您这样做从根本上是错误的。 C++ 程序员声称有权调用未定义的行为并处理这样做的后果。结果并不是很好,未定义的行为是恶意软件非常有吸引力的攻击媒介。您可能不在乎,您的 CRT 供应商会。您的 _invalid_parameter_handler 预计会终止程序或引发异常。你不这样做。接下来发生的是,嗯,undefined。
-
我同意你的真实代码。这只是一个概念证明(或者说是问题证明)。无效参数处理程序没有退出或中断的唯一原因是将行为与控制到达那里之前退出的情况进行对比。当出现无效参数时,我不希望继续执行。我想要一个 DebugBreak 冒泡,我想要一个关于它的弹出窗口。现在我的机器已经修好了(如我的回答中所述),它会停止执行并让我对其进行调查。
标签: c++ windows multithreading visual-studio