pthread 에서 pthread_join 이후 pthread_t 값

dehac의 이미지

두번째 소스코드에서 p_thread[0] 값이 NULL 이 되는 이유를 모르겠네요.
혹시 아시나요?

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
 
void *t_function(void *data) {
        int id;
        int i=0;
        id = *((int *)data);
 
        while(1){
                printf("%d : %d\n", id, i);
                i++;
                sleep(1);
 
                if(i == 5) break;
        }
 
        return (void *)i;
}
 
int main() {
        pthread_t p_thread[3];
        int thr_id;
        int status[3];
        int a=1;
        int b=2;
        int c=3;
 
        thr_id = pthread_create(&p_thread[0], NULL, t_function, (void *)&a);
        if(thr_id < 0) {
                perror("thread create error:");
                exit(0);
        }
        thr_id = pthread_create(&p_thread[1], NULL, t_function, (void *)&b);
        if(thr_id < 0) {
                perror("thread create error:");
                exit(0);
        }
        thr_id = pthread_create(&p_thread[2], NULL, t_function, (void *)&c);
        if(thr_id < 0) {
                perror("thread create error:");
                exit(0);
        }
 
        printf("%d/%d/%d\n", p_thread[0], p_thread[1], p_thread[2]);
 
        pthread_join(p_thread[0], (void **)&status[0]);
        if(p_thread[0] == NULL) printf("NULL : ");
        printf("%d : %d\n", p_thread[0], status[0]);
 
        pthread_join(p_thread[1], (void **)&status[1]);
        if(p_thread[1] == NULL) printf("NULL : ");
        printf("%d : %d\n", p_thread[1], status[1]);
 
        pthread_join(p_thread[2], (void **)&status[2]);
        if(p_thread[2] == NULL) printf("NULL : ");
        printf("%d : %d\n", p_thread[2], status[2]);
 
        return 0;
}

결과:
1116952896/1127442752/1137932608
1 : 0
2 : 0
3 : 0
1 : 1
2 : 1
3 : 1
1 : 2
2 : 2
3 : 2
1 : 3
2 : 3
3 : 3
1 : 4
2 : 4
3 : 4
1116952896 : 5
1127442752 : 5
1137932608 : 5

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
 
void *t_function(void *data) {
        int id;
        int i=0;
        id = *((int *)data);
 
        while(1){
                printf("%d : %d\n", id, i);
                i++;
                sleep(1);
 
                if(i == 5) break;
        }
 
        return (void *)i;
}
 
int main() {
        pthread_t p_thread[3];
        int thr_id;
        int status0=0;
        int status1=0;
        int status2=0;
        int a=1;
        int b=2;
        int c=3;
 
        thr_id = pthread_create(&p_thread[0], NULL, t_function, (void *)&a);
        if(thr_id < 0) {
                perror("thread create error:");
                exit(0);
        }
 
        thr_id = pthread_create(&p_thread[1], NULL, t_function, (void *)&b);
        if(thr_id < 0) {
                perror("thread create error:");
                exit(0);
        }
        thr_id = pthread_create(&p_thread[2], NULL, t_function, (void *)&c);
        if(thr_id < 0) {
                perror("thread create error:");
                exit(0);
        }
 
        printf("%d/%d/%d\n", p_thread[0], p_thread[1], p_thread[2]);
 
        pthread_join(p_thread[0], (void **)&status0);
        if(p_thread[0] == NULL) printf("NULL : ");
        printf("%d : %d\n", p_thread[0], status0);
 
        pthread_join(p_thread[1], (void **)&status1);
        if(p_thread[1] == NULL) printf("NULL : ");
        printf("%d : %d\n", p_thread[1], status1);
 
        pthread_join(p_thread[2], (void **)&status2);
        if(p_thread[2] == NULL) printf("NULL : ");
        printf("%d : %d\n", p_thread[2], status2);
 
        return 0;
}

결과:
1100933440/1111423296/1121913152
1 : 0
2 : 0
3 : 0
1 : 1
2 : 1
3 : 1
1 : 2
2 : 2
3 : 2
1 : 3
2 : 3
3 : 3
1 : 4
2 : 4
3 : 4
NULL : 0 : 5
1111423296 : 5
1121913152 : 5

chanik의 이미지

아마도 64-bit Linux에서 테스트중이실 것 같은데요.
64-bit OS에서는 포인터가 8-byte를 차지하므로 pthread_join(pthread_t pid, (void **)&status); 호출하실때
두 번째 인자인 status는 4-byte 타입인 int 말고 long long같은 8-byte 타입으로 정의하셔야 합니다.

4-byte 공간의 포인터를 넘겨주었는데 pthread_join() 내부에서는 8-byte를 덮어쓰기 때문에 생기는 현상입니다.
첫번째 샘플도 같은 문제를 안고있는데 실행경로상 우연히 런타임 오류를 피해가고 있을 뿐입니다.
첫 샘플에서도 매 join 시마다 아래와 같이 status 배열 모두를 인쇄하도록 해 보시면 부작용이 보일 것입니다.

printf("%d : %d\n", p_thread[0], status[0]);
printf("%d : %d\n", p_thread[1], status[1]);
printf("%d : %d\n", p_thread[2], status[2]);

dehac의 이미지

명쾌한 답변 감사합니다.
64bit OS 맞습니다.
long으로 바꾸니 문제없이 동작합니다. ^^

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.