[완료] Gcc4.4 AMD64 에서 void* 로 int 넘기기
글쓴이: coldfury / 작성시간: 수, 2010/08/25 - 3:05오후
pthread_create( &threads[i], NULL, &thread_main, (void*)i );
보통 thread를 만들 때 이렇게 만들고
void *thread_main( void *arg ){ int index = (int)arg; ... }
이렇게 쓰는걸로 아는데요. 64비트에서 컴파일하니
error: cast from 'void*' to 'int' loses precision
이런 에러가 나더군요.
void*형 포인터의 크기가 int형보다 커서 그런 에러가 나는것 같은데요.
void *thread_main( void *arg ){ int index = (intptr_t)arg; ... }
이렇게 해결했습니다.
그런데, 제가 생각한 문제의 원인이 맞는건지, 해결방법은 안전한건지 의견을 듣고 싶습니다.
Forums:
< pthread_create(
< pthread_create( &threads[i], NULL, &thread_main, (void*)i );
> pthread_create( &threads[i], NULL, &thread_main, (void*)&i );
< int index = (int)arg;
> int index = *(int*)arg;
음 확인은 안해봤지만 이래야 할것 같네요.(64비트랑은 상관없는 내용입니다.)
------식은이 처------
길이 끝나는 저기엔 아무 것도 없어요. 희망이고 나발이고 아무 것도 없어.
첫번재로, i 라는
i 라는 값이 지역 변수라면, 쓰레드가 참조하는 시점에서 i 값이 스코프를 벗어났을 경우,
쓰레드에서 참조할 시점에서 다른 값으로 변경되었을 경우,
(게다가 질문자의 변수 이름으로 봐서는 반복문에서 사용하는 변수 같은데, 이 경우는 참조 시점에서 거의 변한다고 보여집니다.)
문제가 발생합니다.
----
내 블로그: http://unipro.tistory.com
내 블로그: http://unipro.tistory.com
맞는 것 같네요...
다른 방법으로는 long long으로 캐스팅 한 다음 다시 int로 하면 된다네요. void*경우는 주소값이기때문에 32비트값만 덜렁 남아버리면 심각해지기 떄문에 컴파일러에서 금지를 시켜 놓는다는 듯..
저도 해봤는데 경고가 나오네요
Ubuntu 10.04, gcc 4.4.3입니다.
void *arg = 0;
int i = (int)arg;
위 두줄을 시험해봤습니다.
제가 알기로 intptr_t는 64bit에서 일반적으로 long int 로 typedef 되니 자료형 크기는 여전히 차이가 날 것 같습니다.
그런데 gcc에서는 정수형끼리 자료형크기가 다른 것은 경고를 내지 않는군요. -Wall에 -pedantic 도 줘봤지만 역시 안나네요.
제 생각에 우선적으로 void *에서 intptr_t로 변환될 때 자료손실은 발생할 것 같지 않고, intptr_t와 int가 내부표현이 다른 환경에서라도 같은 정수형 사이의 변환이 C에서 보증할 것으로 예상되기 때문에 처음 void *로 넘긴 자료가 int 범위를 넘지 않는 정수라면 문제없을 거라고 봅니다.
해보진 않았습니다만
해보진 않았습니다만 ;
i가 꼭 int type이어야 하는 것이 아니라면 ;;
그냥 intptr_t 로 선언하면 되지 않나요. ;;
댓글 달기