2016-05-31 5 views
0

pthread_join 또는 pthread_detach을 호출하여 알 수 있듯이 스레드가 완료된 후에 스레드에서 사용하는 리소스를 릴리스하지만 상황은 쉽지 않습니다.pthread가 완료된 후 메모리가 누수 됨

우선 부모 스레드에서 자식 스레드를 종료 할 수 있기를 원하므로 다음과 같이 씁니다. (동적 할당 된 buf가 사용 방법을 찾지 못하는 것으로 나타납니다. pthread_detach 나는 (내가 버피를 확보 할 수 있습니다) 내가 그것을 분리하는 경우)

bool running = true; 
void *foo(void *buf) 
{ 
    while (running) 
    { 
     // Do something with buf 
    } 

    return NULL; 
} 

int main(int argc, char **argv) 
{ 
    char *buf = new char[1024]; 

    pthread_t tid; 
    pthread_create(&tid, NULL, foo, buf); 

    string cmd; 
    while (true) 
    { 
     cin >> cmd; 

     if (!cmd.compare("stop")) 
     { 
      running = false; 
      pthread_join(tid, NULL); 
      delete[] buf; 
     } 
     else 
     { 
      // Do something 
     } 
    } 

    return 0; 
} 

이 작동하는 것 같다 마무리 자식 스레드 대기하는 방법을 모르기 때문에. 그러나 자식 스레드는 부모 스레드가 종료하기 전에 완료되기도합니다. 이 경우, 부모 스레드가

  1. 가 어떻게 부모 스레드가 pthread_join를 호출 할 수 있도록 자식 스레드가 종료 된 것을 부모 스레드를 통보 않도록 차단?

  2. pthread_detach을 사용하는 방법이 있습니까? 그렇다면 나중에 버프를 해제 할 수 있도록 자식 스레드가 끝날 때까지 기다릴 수 있습니까 (이 데모의 자식 스레드에서 buf를 해제 할 수는 있지만 내 실제 응용 프로그램)?

+0

여기에 무엇을 하려는지 확실하지 않습니다. 'pthread_join'은 쓰레드가 완료 될 때까지 블럭합니다. 스레드가 종료하는 데 오랜 시간이 걸리면 종료가 누락 될 염려는 없습니다. – user4581301

+0

@ user4581301 문제는'pthread_join'을 사용하면 자식 스레드가 끝날 때 상위 스레드에게'pthread_join'을 호출해야한다는 것입니다. 대신'pthread_detach'를 사용하면 자식 스레드가 끝날 때까지 기다릴 수 없습니다. – MegaStupidMonkeys

답변

2
  1. 어떻게 부모 스레드가 pthread_join을 호출 할 수 있도록 자식 스레드가 종료 된 것을 부모 스레드를 알릴 수 있습니까?

모든 종류의 옵션이 있습니다. 합리적으로 유망한 세 가지가 있습니다 :

  • 자식 스레드가 전역 플래그 변수를 설정할 수 있습니다.

  • 자식 스레드가 부모 스레드에 pthread_kill()이라는 신호를 보낼 수 있습니다.

  • 자식이 끝날 때 작성하는 파이프를 설정할 수 있으며 부모가 자식이 끝났는지 여부를 테스트하기 위해 부모가 비 차단 읽기를 수행하도록 할 수 있습니다.

  1. 는 것 같다 (비록 내가 할 수있는 나중에 버피을 완료 자식 스레드 기다릴 그래서 확보 할 수 있습니다 할 수 여전히 pthread_detach를 사용하는 방법이 있나요 이 데모의 하위 스레드에서 무료 buf, 불가능합니다 내 실제 응용 프로그램에 대한 )?

아니요. 일단 스레드를 분리하면 스레드를 결합 할 수 없습니다.

대신 스레드가 자체 리소스를 관리하도록 고려해 볼 수 있습니다. 또는 메인 스레드가 리소스를 할당해야한다면 최소한 자식 스레드에 대한 관리 책임을 넘기는 것을 고려해보십시오.

0

부모 스레드가 pthread_join을 호출 할 수 있도록 부모 스레드에 자식 스레드가 종료되었음을 알리는 방법은 무엇입니까?

std :: thread를 사용 해본 적이 있습니까?

다음 코드는 std :: thread를 사용하지 않아도된다는 것을 보여줍니다. sleep_for()는 인간이보기에 충분히 크다.

void pause_thread(int n, std::string lbl) 
{ 
    std::this_thread::sleep_for (std::chrono::seconds(n)); 
    std::cout << lbl << " pause of " << n << " seconds ended" << std::endl; 
} 

int t403(void) 
{ 
    std::cout << "Spawning 3 threads...\n" << std::flush; 
    std::thread t1 (pause_thread, 6, "t1"); 
    std::thread t2 (pause_thread, 3, "t2"); 
    std::thread t3 (pause_thread, 1, "t3"); 
    std::cout << "Done spawning threads, " 
     "Note that they finish out-of-order. \n" 
     "Now 'main' thread waits for spawned threads to join:\n" << std::flush; 

    t1.join(); std::cout << "join t1 " << std::flush; 
    t2.join(); std::cout << "join t2 " << std::flush; 
    t3.join(); std::cout << "join t3 " << std::flush; 
    std::cout << "completed join \n" 
     "note: \n - join sequence is in-order, but finish sequence is out-of-order\n" 
     " - inference: the threads waited for main to join! "<< std::endl; 

    return(0); 
} 

업데이트 : 2016년 6월 1일

나는 POSIX 스레드와 조인을 사용하여 위의 기법을 재현했다. 주 스레드는 생성 된 스레드가 종료되었음을 알리는 메시지가 필요하지 않습니다. "사람 pthread_join을"에서도

:

pthread_join을() 함수가 종료 '스레드' (파라미터 1)에 의해 지정된 스레드에 대해 대기한다. 해당 스레드가 이미 종료 된 경우 pthread_join()이 즉시 반환됩니다. 스레드로 지정된 스레드는 결합 가능해야합니다.

아마도 질문에 대해 누락되었습니다.

아마도이 조인을 실행하는 스레드가이 시간 동안 다른 작업을 시도해서는 안됩니다.

"다른 것"을 자체 협업 스레드로 이동하는 것을 고려해보십시오.

0

나는 다른 방향으로 향할 것입니다. "buf을 출시 할 수 있도록 스레드 끝을 알리는 방법은 무엇입니까?" "buf에 대해 소유권을 어떻게 할당해야합니까? 스레드 끝이 중요하지 않은 방식으로하는 것이 바람직합니까?"

foo 또는 mainbuf을 릴리스해야합니다. 그래서?

사례 1 : buf이 경우 buf 할당 및 스레드 처리가 완료되면 buf을 소비하지 않는 것이면 mainmainmain 초기화

포함하여 할당하지만 미사용된다. 이 경우는 쉽습니다. 스레드는 소유권을 buf으로 간주하고 스레드가 완료되면 삭제합니다.

void *foo(void *buf) 
{ 
    while (running) 
    { 
     // Do something with buf 
    } 
    delete buf; 
    return NULL; 
} 

케이스 2 : bufmain로 할당하고 main 의해 소비 foo 의해 동작.

분명히 buf 그래서 main 소유권을 유지하고 소모 후 buf을 삭제해야합니다, main이 소비하기에 살아 있어야합니다. 하지만 때? 즉, foo이 처리 완료 buf을 기다려야한다는 것을 의미합니다. 이는 결합 또는 완료 메시지를 의미합니다. 이제 John Bollinger의 대답을 얻습니다.

사례 3 : buffoo에 의해 동작되고, foo에 의해 동작되고, foo에 의해 삭제된다.

이것은 무엇을 그리 적없는 혼란의 장점을 가지고 있으며, main 결코 buf을 접촉하지 않는 경우, main 완전히 할당을 포함 손 - 오프이어야한다. main에 알려진 경우

void *foo(void *) 
{ 
    char buf[1024]; 
    while (running) 
    { 
     // Do something with buf 
    } 
    return NULL; 
} 

버퍼의 크기가 아니라 foo에 스레드에게 제공 할 수 있습니다처럼 완벽한 세상에서는이 보인다. 예를 들어,

pthread_create(&tid, NULL, foo, &bufsize); 

void *foo(void * size) 
{ 
    char * buf = new char[*((int*)size)]; 
    while (running) 
    { 
     // Do something with buf 
    } 
    delete buf; 
    return NULL; 
} 

하지만 당신은

void *foo(void * size) 
{ 
    std::unique_ptr<char[]> buf(new char[*((int*)size)]); 
    while (running) 
    { 
     // Do something with buf 
    } 
    return NULL; 
} 

원시 포인터를 방지하는 것을 선호한다.

foo이 시작되기 전에 bufsize이 변경되지 않았는지 확인하십시오.

관련 문제