2011-12-01 5 views
0

다음 코드는 다음과 같습니다. 코드가 완전하지 않아, 리소스 부분을 해제하고 QueryRes 로직을 구현하지 않았다. (*) 장소에서WaitForSingleObject가 충돌 함

#define N 5 

/*simply resources manager which has N shared resources*/ 
class ResourceManager 
{ 
public: 
    ResourceManager() 
    { 
      for (int i = 0; i < N; ++i) 
       resources[i] = CreateMutex(NULL, FALSE, NULL); 
    } 
/*CreateMutex for on resources array in ctor*/ 
/*CloseHandle() in dtor and ReleaseMutex in another function which is called after QueryRes*/ 

     void QueryRes(int i) 
     { 
      WaitForSingleObject(resources[i], INFINITE); //(*) Here is the problem 
     } 

private: 
     HANDLE resources[N]; 
}; 

/*User who asks for resource time-to-time*/ 
class User 
{ 
public: 
    User(ResourceManager& res_holder_, int res_num) : resource_holder(resource_holder), resource_to_query(res_num) {} 

    void WorkWithResource() 
    { 
      while(1) 
      { 
        resource_holder.QueryRes(resource_to_query); 
      } 
    } 


    static void Run (void* params) 
    { 
      static_cast<User*>(params)->WorkWithResource(); 
    } 

private: 
    ResourceManager& resource_holder; 
    int resource_to_query; 
}; 

int main() 
{ 
     ResourceManager resource_manager; 
     User* users[5]; 
     HANDLE threads[5]; 

     for (size_t i = 0 ; i < 5; ++i) 
     { 
       users[i] = new User(resource_manager, i % 5); 
       threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&User::Run, users[i], 0, NULL); 
     } 
     WaitForMultipleObjects(5, threads, true, INFINITE); 


     return 0; 
} 

내가 "액세스 위반 예외"GET 함수는 이미 잠긴 뮤텍스에 WaitForSingleObject을 수행 할 때.

는 또한
while(WaitForSingleObject(resources[i], INFINITE) != WAIT_OBJECT_0) 

을 시도하고 같은 결과를 얻었다.

예외가 발생하는 이유는 무엇입니까?

vc 2003, 2008 및 2010을 시도했습니다. boost/pthreads/etc를 사용할 수 없습니다.

감사합니다.

+0

'ResourceManager'에서 N 값은 얼마입니까? – Pablo

+0

'(HANDLE resources [N];에서)'N '선언을 포함 할 수 있습니까? – hmjd

+0

당신은'ResourceManager'의 생성자를 보여줄 필요가 있습니다. – Chad

답변

4

오류는 대신

User(ResourceManager& res_holder_, int res_num) : resource_holder(**res_holder_**), resource_to_query(res_num) { } 

을 가져야한다

User(ResourceManager& res_holder_, int res_num) : resource_holder(resource_holder), resource_to_query(res_num) { } 

의 생성자에있다!

+0

하나님, 당신을 축복합니다. 나는이 실수로 하루 반을 보냈습니다! – fogbit

1

액세스 위반 (또는 다른 플랫폼에서 segfault가 발생하는 경우 일반적으로 이것은 잘못된 포인터 참조 해제이지만) 종종 코드를 보면 분명히 알 수 있습니다 ...이 경우에는 나에게서 어떤 것도 튀어 나오지 않습니다. 당신이 올린 내용. 네가 한 말에 근거한 내 추측은 무언가를 뭉개 버린 것입니다.

그러나 약간의 조언 ... 설명 할 수없는 액세스 위반이 발생하면 첫 번째 단계는 스택 오버플로에 게시하지 않는 것입니다. 그것을 디버거에서보십시오! Microsoft에서 "Windows 용 디버깅 도구"를 다운로드하고 "windbg"을 사용하고 사용 방법을 배우면 액세스 할 수있는 잘못된 주소는 무엇인지 알 수 있다고 생각한 것보다이 충돌에 대해 자세히 알려줍니다. disbuembly of WaitForMultipleObjects 그래서 내가하는 일과 주소가 어디서 왔는지 볼 수 있습니다. 보통 windbg에서 약간의 k, r, udq 명령을 사용합니다. 잘못된 포인터 역 참조가 발생하는 이유는 아주 명백합니다.

+0

저는 디버거를 반나절 반쯤 쳐다 보았습니다. 충돌 할 때마다 winapi 함수를 디버깅합니까? 나는 내가 몇 가지 잘 알려진 실수를 저질렀다고 생각했다. – fogbit

+0

@fogbit 사실, 내 것이 아닌 함수에서 크래시가 발생하면 'u'(디버그)로 디버깅합니다. OS 또는 라이브러리 함수와 같은 경우 일반적으로 잘못된 포인터를 제공했음을 의미합니다. 즉, 오류가 발생한 포인터는 사용자가 수행 한 작업에서 파생 된 포인터입니다.그런 식으로 크래시를 디버깅 할 때 시스템에 대한 전체적인 시각을 가져야합니다. 코드와 API 간의 모든 계층화 및 추상화 및 구별이 올바르지 않게 수행되어야합니다. – asveikau