2012-11-03 17 views
5

Zrobiłam próbkę, aby sprawdzić, co się stanie, gdy Ctrl + C jest wciśnięty w oknach aplikacji konsoli:dlaczego coraz pierwszy wyjątek Chace w C++

bool TerminationFlag=true; 

int main() 
{ 
    g_hTerminateEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); 
    ::SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE); 
    while(1) 
    { 
     if(TerminationFlag == false) 
     { 
      break; 
     } 
    } 
    return 0; 
} 

BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType) 
{ 

    if (dwCtrlType == CTRL_C_EVENT || 
     dwCtrlType == CTRL_BREAK_EVENT || 
     dwCtrlType == CTRL_CLOSE_EVENT) 
    { 
     TerminationFlag=false; 
     ::SetEvent(g_hTerminateEvent); 
     return TRUE; 
    } 
    return FALSE; 
} 

I badanego kodu uruchamiając go za pomocą rozpocząć debugowanie opcję wizualnej studio po naciśnięciu ctrl + C otrzymuję następujący komunikat

Pierwsza szansa wyjątek w 0x7c87647d

kiedy Wciś nię cie kontynuacji opcji mój kod dochodzi do linii TerminationFlag=false; mimo, że obsługuję Ctrl + C w obsłudze kontrolnej. Czy możesz mi powiedzieć, jaki jest problem?

+0

Kiedy pojawia się wyjątek pierwszej szansy, spójrz na rekord wyjątku, aby zobaczyć, co się podnosi i dlaczego. –

+0

@RaymondChen jak spojrzeć na rekord wyjątku sir? – Dany

+0

Rekord wyjątków jest częścią wyrażenia "EXCEPTION_POINTERS" przekazanego do obsługi wyjątku. Niektóre debuggery mają specjalne polecenie do wyświetlenia bieżącego rekordu wyjątku. (Na przykład windbg używa '.ecxr'.) –

Odpowiedz

11

Zakładam, że korzystasz z Microsoft Visual Studio z opisu problemu. Podnoszonym wyjątkiem pierwszej szansy jest zdarzenie CTRL-C, które jest uwięzione przez środowisko debugowania. To jest oczekiwane zachowanie.

Możesz to zignorować: przejdź do menu Debuguj/Wyjątki/Wyjątki Win32 i wyjmij kontrolę CONTROL-C z menu kolumny "Zrzucone". Zapewni to, że debugger łamie tylko CONTROL-C, gdy jest nieobsługiwany przez użytkownika. Patrz zdjęcie poniżej:

enter image description here

Nawiasem mówiąc, należy oczekiwać na razie wypowiedzenia nie odpytywania na fladze. Możesz chcieć coś takiego:

#include "windows.h" 
#include <iostream> 
HANDLE g_hTerminateEvent; 

BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType) 
{ 

    if (dwCtrlType == CTRL_C_EVENT || 
     dwCtrlType == CTRL_BREAK_EVENT || 
     dwCtrlType == CTRL_CLOSE_EVENT) 
    { 
     std::cout << "Terminating" << std::endl; 
     SetEvent(g_hTerminateEvent); 

     return TRUE; 
    } 
    return FALSE; 
} 
int main() 
{ 
    g_hTerminateEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); 
    SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE); 

    DWORD result = WaitForSingleObject(g_hTerminateEvent, INFINITE); 
    return 0; 
} 
+0

Próbowałem, co powiedziałeś, ale nadal otrzymuję wyjątek "Pierwszy przypadek wyjątek 0x7c87647d w smallsample.exe: 0x40010005: Control-C."na pressinf ctrl + c – Dany

+0

Cześć Dany, sprawdź zdjęcie z przykładu - upewnij się, że odbudujesz plik wykonywalny po wyczyszczeniu flagi 40001005 (Ctrl-C) Sprawdź ustawienia ... – Anthill

+0

Myślę, że rozumiem źródło twojego zamieszania: CTRL -C jest przerwaniem, a Visual Studio generuje DBG_CONTROL_C w trybie debugowania dla wygody, Ctrl-C nie jest wyjątkiem, zgłaszanym jest wyjątek DBG_CONTROL_C generowany przez tryb debugowania. – Anthill

1

Po uruchomieniu tego rodzaju rzeczy w debugerze nigdy nie otrzymasz tego samego obrazu, jakbyś działał bez debuggera. W debuggerze zazwyczaj nie można przekroczyć funkcji systemowych, które powodują wejście/wyjście konsoli. Debugger będzie tu nieunikniony w interakcji z systemem.

Najbardziej niezawodnym sposobem na kontynuowanie jest śledzenie.

To może nie odpowiadać bezpośrednio na pytanie.

p.s. W swoich próbkach kodu, tak jak teraz, nie ma potrzeby występowania zdarzenia.

Update z MSDN:

Value Meaning 
0 CTRL_C_EVENT 

sygnał ctrl + C otrzymano albo z klawiatury lub z sygnału generowanego przez funkcję GenerateConsoleCtrlEvent.

+0

dzięki za odpowiedź sir, więc co mam zrobić? – Dany

+0

Polecam umieścić w instrukcji obsługi polecenie print, które powinno wydrukować wartość odebranego parametru. –

+0

sir Otrzymuję wartość 0 w DWORD dwCtrlType, gdy pree ctrl + c – Dany

Powiązane problemy