CRT参数验证使多线程调试程序崩溃



以下代码在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 handlern");
    _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)弹出"中止/重试/忽略",并在必要时保持不变。如果我点击"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)的评论,那么它会达到我的预期。我们得到两个中止/重试/忽略弹出窗口,它们挂起,主线程运行到完成。

发布版本不存在此问题,会为两个线程调用无效的参数处理程序,并且始终继续执行。


对于上下文,我们有一个长时间运行的服务器进程,它在多个线程中命中_isatty(-1)并静默退出。这是一个我们已经解决的问题,但这种行为使追踪变得非常困难。我想知道是否有什么可以帮助的。

我看到一个有类似行为的问题,但那是MinGW&被确定为编译器错误。我已经验证了该测试在VS2012中有效。

弄清楚了——不知怎么的,我在注册表中禁用了调试。HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionAeDebug中的密钥Auto丢失。将其设置为1会导致调用Debugger键中命名的调试器vsjitdebugger。没有什么消失了!

这个想法来自http://support.microsoft.com/kb/188296关于禁用Watson。

最新更新