2013-06-28 20 views
0

下面的代码将按预期在VS2012,调试版本:CRT参数验证崩溃多线程调试程序

#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; 
} 

参数验证将导致“中止/重试/忽略”从childThread的_isatty(-1)弹出,它总是在那里,只要有必要。如果我点击“忽略”,然后调用myInvalidParameterHandler,并且程序运行,直到我按Enter。都好。


如果第二CreateThread未被注释于是两个参数验证失败发生在一次,然后该程序退出静默。有时中止/重试/忽略弹出,但它在一秒钟内消失。该程序永远不会挂起主要的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)在多线程和默默退出长时间运行的服务器进程。这是我们修复的一个问题,但是这种行为使得追踪非常困难。我想知道是否有什么可以做的帮助。

我看到一个question with similar behavior,但那是MinGW &被确定为编译器bug。我已经证实,测试在VS2012中起作用。

+0

你正在做这个很根本错误的。 C++程序员声称有权调用未定义的行为并处理这样做的后果。这并没有得到太好的结果,未定义的行为是一个非常有吸引力的恶意软件攻击媒介。您可能不在意,您的CRT供应商会这么做。你的_invalid_parameter_handler是** expected **来终止程序或抛出异常。你不这样做。接下来会发生的是,* undefined *。 –

+0

我同意你的真实代码。这仅仅是一个概念证明(或者证明问题)。无效参数处理程序没有退出或中断的唯一原因是将行为与控制到达之前退出的情况进行对比。 我不想在发生无效参数时继续执行。我想要一个DebugBreak泡沫,我想要得到一个关于它的弹出窗口。现在我的机器是固定的(如我的回答中所述),它停止执行并让我调查它。 –

回答

1

想通了 - 不知何故,我在我的注册表中禁用了调试功能。他们的钥匙AutoHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug丢失。将其设置为1会导致调用名为Debugger的调试器vsjitdebugger。没有消失了!

http://support.microsoft.com/kb/188296得到关于禁用沃森的想法。

+0

半相关:从Cygwim运行程序时,我仍然没有收到任何调试弹出窗口,但是我在从cmd运行时执行了此操作。这解决了这个问题:http://超级用户。COM /问题/ 197397 /无碰撞的对话中,当-A-程序崩溃-ON-cygwin的上窗口-7 –