2015-05-12 22 views
7

Niektóre tła: Próbuję śledzić błąd, który powoduje u mnie poważne bóle głowy. Po wielu ślepych zaułków (patrz this question) I wreszcie skończył z tym kodem:Program zawiesza się w debugerze Visual Studio

#include <thread> 
#include <vector> 
#include <iosfwd> 
#include <sstream> 
#include <string> 
#include <windows.h> 

int main() 
{ 
    SRWLOCK srwl; 
    InitializeSRWLock(&srwl); 
    for(size_t i=0;i<1000;++i) 
    { 
     std::vector<std::thread>threads; 
     for(size_t j=0;j<100;++j) 
     { 
      OutputDebugString("."); 
      threads.emplace_back([&](){ 
       AcquireSRWLockExclusive(&srwl); 
       //Code below modifies the probability to see the bug. 
       std::this_thread::sleep_for(std::chrono::microseconds(1)); 
       std::wstringstream wss; 
       wss<<std::this_thread::get_id(); 
       wss.str(); 
       //Code above modifies the probability to see the bug. 
       ReleaseSRWLockExclusive(&srwl);}); 
     } 
     for(auto&t:threads){t.join();} 
     OutputDebugString((std::to_string(i)+"\n").data()); 
    } 
    return 0; 
} 

Kiedy uruchomić ten kod wewnątrz VS 2013 debuggera program zawiesza się przy wyjściu jak ten:

....................................................................................................0 
....................................................................................................1 
....................................................................................................2 
........................... 

dziwne Wystarczy, że jeśli wstrzymam debuggera i sprawdzę, co się dzieje, jeden z wątków znajduje się wewnątrz AcquireSRWLockExclusive (w NtWaitForAlertByThreadId), najwyraźniej nie ma powodu, dla którego program się zawiesił. Kiedy klikam przycisk "wznów", program z radością kontynuuje i drukuje więcej rzeczy, dopóki nie zostanie ponownie zablokowany.

Czy masz pojęcie, co się tutaj dzieje?

Niektórzy więcej informacji:

  • O ile mogę powiedzieć, ten błąd występuje tylko w systemie Windows 8.1.
  • Próbowałem VS2013.4 i VS2015 RC.
  • Mogę odtworzyć go na dwóch różnych komputerach w systemie Windows 8.1.
  • Jedna maszyna została sformatowana, pamięci RAM, procesora i przetestowane Disk (myślałem o awarii, ponieważ na początku nie mogłem tylko obserwować błąd na tej konkretnej maszynie)
  • nigdy nie mogłem odtworzyć go na Windows 7.
  • Może być przydatne zmodyfikowanie kodu między komentarzami w celu obserwacji błędu. Kiedy dodałem mikrosekundowy sen, mogłem w końcu odtworzyć błąd na innym komputerze.
  • Dzięki VS2015 RC mogłem odtworzyć to samo zachowanie przy prostym std :: mutex. W VS2013 jednak SRWLOCK wydaje się obowiązkowy, aby obserwować błąd.
+0

Możliwe, że jesteś w martwym punkcie i po wejściu do debuggera zmienia on synchronizację i zakleszczenie znika. – NathanOliver

+0

@NathanOliver Jak to możliwe? W kodzie jest tylko jeden muteks. – Arnaud

+0

Czy program kiedykolwiek zawiesza się po uruchomieniu poza debuggerem? –

Odpowiedz

4

Ten problem jest spowodowany przez błąd harmonogramu systemu operacyjnego wprowadzony w aktualizacji wiosną 2014 roku do systemu Windows 8.1. Poprawka tego problemu została wydana w maju 2015 r. I dostępna pod adresem https://support.microsoft.com/en-us/kb/3036169.

+0

Próbowałem poprawkę i rozwiązuje problem. Wydaje się jednak, że jest znacznie wolniej. – Arnaud

1

Dla mnie wygląda jak błąd w systemie operacyjnym Windows, mam różne warianty kodu, które zawiesza się przy użyciu nowych prymitywów systemu Windows Vista w debugerze w wersji 8.1/Server 2012R2 po aktualizacji z kwietnia 2014 r. Również zawiesza się także funkcja oczekiwania na pulę wątków. Wygląda na to, że jest to głównie związane z innymi zakończonymi wątkami w momencie oczekiwania/blokady. Oto prosty kod, który zawsze wisi pod debugger w NtWaitForAlertByThreadId():

#include <windows.h> 

#include <stdio.h> 
#include <conio.h> 
#include <tchar.h> 

#pragma optimize("",off) 
VOID CALLBACK _WorkCallback(PTP_CALLBACK_INSTANCE Instance, PVOID pUser, PTP_WORK Work) 
{ 
    for (int i = 0; i < INT_MAX/256; i++) {} 
} 

DWORD WINAPI ThreadProc(LPVOID lpParameter) 
{ 
    for (int i = 0; i < INT_MAX/256; i++) {} 
    return 0; 
} 
#pragma optimize("",on) 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    LONGLONG c = 0; 

    while(!_kbhit()) 
    { 
     PTP_WORK ptpw = CreateThreadpoolWork(&_WorkCallback, NULL, NULL); 
     if (ptpw != NULL) 
     { 
      for(long i = 0; i < 3; i++) SubmitThreadpoolWork(ptpw); 

      CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); 

      WaitForThreadpoolWorkCallbacks(ptpw, FALSE); 
      CloseThreadpoolWork(ptpw); 
     } 

     printf("%I64d         \r", c++); 
    } 

    _getch(); 
    return 0; 
} 

Niestety nie mam pojęcia, gdzie zgłosić je do firmy Microsoft.

+0

Mogę również powielić zawieszenie w moim systemie. – Arnaud

Powiązane problemy