2012-07-26 5 views
1

분할 오류의 사례를 이해할 수 없습니다.pthread_join()의 분할 오류

int main() 
{ 
    int val; 
    pthread_t thread; 
........................... 
    pthread_join(thread,(void **) &val); 
    printf("Val=%d",val); 
//and here sometimes come segmentation 
//fault and other times i get correct val value 

........................... 
} 

void *Do(void *) 
{ 
    int retval=4; 
............... 
    pthread_exit((void *) retval); 
} 

제가 있어 올바른 경우, 그 발 = 4 pthread_join을 후()을 의미한다 (& 브로) 포인터가 가리키는 변수로 (4 값)가 pthread_exit()를 저장 요지. 하지만 제가 여러 번 프로그램을 시작하면 올바른 발 값 (즉 4)과 다른 출시에 대한 세분화 오류가 발생합니다. (btw 포인터와 Do 함수의 동적 할당으로 올바른 방법으로했을 때와 동일한 결과).

도와주세요. 미리 감사드립니다.

+0

너는 너무 많이 꺼냈다. 추가하는 동안 들여 쓰기를 수정하십시오. – Wug

답변

0

내가 생각할 수있는 유일한 사실은 함수 * 지역 변수의 주소를 반환한다는 사실입니다. 지역 변수는 함수에 대해 할당 된 스택 프레임에 저장됩니다. 스레드가 종료 된 후 유효하지 않은 위치에 대한 포인터를 반환합니다.

참조 :
http://man7.org/linux/man-pages/man3/pthread_exit.3.html

말한다 : 그 스택의 내용이기 때문에

값은, RETVAL가 호출 스레드의 스택에 위치하지 않아야 가리키는 이후에 정의되지 않은 스레드가 종료됩니다.

0
pthread_exit((void *) retval); 

이것은 (결정되지 않은 크기로) 정수를 취하고 다른 잠재적 크기 포인터에 캐스트. 나는 이것이 sizeof (void *)> = sizeof (int)처럼 대부분 괜찮다고 말할 것이다.

pthread_join(thread,(void **) &val); 

이 호출은 실제로 sizeof (int) == sizeof (void *) 인 경우에만 유효합니다. 만약 당신이 64 비트 시스템에 있다면 & val은 4 바이트의 공간을 가리키고 컴파일러에게 8을 가리킨다.이 주소가 할당 된 가상 주소 공간의 끝 부분에 있다면 void 포인터를 쓰려고하는 pthread_join의 segfault.

당신이해야 할 것은 :

void *retval; 
pthread_join(thread, (void **), &retval); 
val = (int)retval; 

INT의 포인터에서 캐스트가 더 중요한 비트 중 하나를 자릅니다. 또한 64 비트 빅 엔디안 시스템이라면 실제로 데이터를 저장하는 4 바이트가 두 번째 4 바이트이므로 올바른 val을 얻지 못할 것입니다.

다른 대답과는 달리 정수 반환 값을 void *로 캐스팅하여 반환 한 다음 원하는 정수 유형으로 다시 전달하는 것이 좋습니다. 정의되지 않은 동작을 호출하는 것처럼 참조 해제하려는 스택의 데이터에 실제 포인터를 전달하기를 원하지 않을 것입니다. 하루가 끝날 때 포인터는 메모리의 일부 위치를 가리키는 부호없는 정수 이상일뿐입니다.