2015-05-12 21 views
7

Bazı arka plan: Başım ağrısına neden olan bir hatayı izlemeyi deniyorum. GaripProgram, Visual Studio hata ayıklayıcısında kilitleniyor

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

: VS içindeki 2013 ayıklayıcısını bu kodu çalıştırdığınızda

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

programı bunun gibi bir çıkış ile asılı: Birçok çıkmaz (this question bakınız) sonra nihayet bu kod ile sona erdi yeterli, Hata ayıklayıcısını duraklatır ve ne olup bittiğini denetlerseniz, iş parçacıklarından biri AcquireSRWLockExclusive (NtWaitForAlertByThreadId içinde) içinde görünür, programın neden asılı olduğu konusunda hiçbir neden yoktur. Özgeçmişi tıkladığımda, program mutlu bir şekilde devam eder ve tekrar engellenene kadar daha fazla şey basar.

Burada neler olduğu hakkında bir fikriniz var mı?

Biraz daha bilgi:

  • Bildiğim kadarıyla söyleyebilirim, bu hata sadece Windows 8.1'de bulunmaktadır.
  • VS2013.4 ve VS2015 RC'yi denedim.
  • Windows 8.1 altında iki farklı bilgisayarda çoğaltabilirim.
  • Ben Windows 7
  • üzerine yeniden asla makinenin
  • biri
  • , RAM, CPU biçimlendirilmiş ve disk test (ilk ben sadece bu özel makinede hata gözlemlemek çünkü ben bir arıza düşünce)
  • Hata gözlemlemek için yorumlar arasındaki kodu değiştirmek yararlı olabilir. Mikrosaniye uykusunu eklediğimde, hatayı başka bir bilgisayarda yeniden üretebilirim.
  • VS2015 RC ile aynı davranışı basit bir std :: mutex ile yeniden üretebilirim. VS2013'de SRWLOCK, hatayı gözlemlemek için zorunlu görünüyor.
+0

Bir çıkmazda olabilirsiniz ve hata ayıklayıcıya girdikten sonra, eşitleme değiştirir ve kilitlenme kaybolur. – NathanOliver

+0

@NathanOliver Bu nasıl mümkün olabilir? Kodda sadece bir muteks var. – Arnaud

+0

Program hata ayıklayıcısının dışında çalışırken takılıyor mu? –

cevap

4

Bu sorun, ilkbahar 2014 güncelleştirmesinde Windows 8.1'e eklenen bir işletim sistemi zamanlayıcısı hatası nedeniyle oluşur. Bu sorun için bir düzeltme Mayıs 2015'te yayımlandı ve https://support.microsoft.com/en-us/kb/3036169 adresinde kullanılabilir.

+0

Düzeltmeyi denedim ve sorunu çözüyor. Yine de çok daha yavaş görünüyor. – Arnaud

1

Benim için Windows işletim sisteminde bir hataya benziyor, Nisan 2014 güncellemesinden sonra Win 8.1/Server 2012R2'de hata ayıklayıcı altında yeni Vista ilkellerini kullanan farklı kod varyantları var. Ayrıca bazı iş parçacığı havuzu bekleme işlevi de askıda kalıyor. Bekleme/kilitleme anında diğer iş parçacığı bitmiş yürütme çoğunlukla bağlı gibi görünüyor.

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

Ne yazık ki Microsoft'a bildirmek için hiçbir fikrim yok: İşte hep NtWaitForAlertByThreadId (içinde ayıklayıcı altında asılı basit kod) 'dir.

+0

Sistemimde de asılı kalabilirim. – Arnaud

İlgili konular