2012-11-25 4 views
4

소켓 프로그래밍에서 작업 중입니다. 코드가 원하는대로 실행되고, 사용할 수 있습니다. 그러나 편집에 대한 경고를 내게줍니다.경고 : 포인터를 다른 크기의 정수로 변환합니다.

나는

gcc server1.c -o server1 -lpthread 

를 사용하여 컴파일 그리고 난 경고를 얻을

warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] 

이 오류는 다음 코드

int newsockfd; 
newsockfd = (int)newsockfdd; //this line 

을 위해 제공 그리고는이 int이며 (newsockfdd를 사용하고 있습니다) 다음 코드 덩어리에

if (pthread_create(&threadID[i++], NULL, serverThread, (void *)(intptr_t)newsockfdd) != 0) 
    { 
     perror("Thread create error"); 
    } 

아마도 당신이 말할 수 있듯이, 코드는 너무 잘 작성되지 않았습니다. (나는 더 잘 만들고 있습니다). 이 경고는 int의 크기와 관련이 있기 때문에 발생한다는 것을 알고 있습니다. 그러나 나는 그것을 고치는 방법을 정말로 모른다. 내가는 pthread_create 문에 (intptr_t)를 넣어 전에, 그 라인에 경고를 표시했지만, 그 시간은 경고

warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] 

했다이에 대한 간단한 수정이 있어야한다 것 같다? 그러나 나는 그것을 발견 할 수 없다. 우분투 64 비트를 사용하고 있습니다. 그것이 경고의 이유입니까? 주석에 확립 된 바와 같이

+0

흠. 캐스트를 'intptr_t'에 삽입하기 전에'(void *) newsockfdd'에서 얻은 경고를 감안할 때, '다른 크기의 정수로 포인터에서 캐스트'경고가 실제로 표시된 줄에서 오는 것 같지 않습니다 . –

+0

... 'serverThread'와'newsockfdd'의 줄은'serverThread'가받는 인수입니까? 그러면 그것은 분명합니다. –

+0

@DanielFischer 예 .. serverThread에 인수로 전달합니다. 이렇게 : void * serverThread (void * newsockfdd). 그래서 무엇이 잘못 되었습니까? – user1825770

답변

6

상황은

void *serverThread(void *arg) { 
    // ... 
    int newsockfd = (int)arg; 
    // ... 
} 

main에서 (또는 거기에서 호출하는 함수) (모듈이 전달 인자 또는 수신 파라미터로서 newsockfdd의 혼란 발생을 피하기 위해 개명) 인 int newsockfddserverThread에 인수로 전달 될 때

// ... 
int newsockfdd = whatever; 
// ... 
if (pthread_create(&threadID[i++], NULL, serverThread, (void *)(intptr_t)newsockfdd) != 0) 
// .. 

그래서, 그것은 void*으로 캐스팅된다. 원래는 그 캐스트가 직접적 이었지만 intptr_t으로 중간 캐스트를 삽입하여 cast to pointer from integer of different size에 대한 경고를 삭제했습니다.

그리고 serverThread에서

, 수신 void*cast from pointer to integer of different size에 대한 경고의 결과로, int으로 캐스팅된다.

경고는 아마도 중간 캐스트를 intptr_t에 삽입하여 제거 할 수도 있습니다.

그러나, 표준 포인터와 그 반대의 정수를 캐스팅 수 있지만, 결과는 구현 정의하고 보장이 없다는 것을 int -> void* -> int 왕복 (표준에서 각주

매핑을 말한다 있지만, 포인터를 정수 또는 정수로 포인터로 변환하는 함수는 이 실행 환경의 주소 지정 구조와 일치하도록되어 있습니다.

그래서 아마 그 것이다이 경우 의도 한대로 왕복 및 작업 -하지만 가능성이 void*의 크기보다 작은 경우 [에만 정도로 작은 절대 값의 값] 작동하지 않을 것입니다 정수형 [32 비트 시스템에서는 long long -> void* -> long long을 고려하십시오]).

적절한 수정 정수과 포인터 사이의 주조를 피하기 위해, severThread

void *serverThread(void *arg) { 
    // ... check that arg isn't NULL 
    int newsockfd = *(int *)arg; 
    // ... 
} 

는 적절한 타입의 포인터를 수신 한 포인터를 캐스팅하고 지적하는 값과의 main

읽기
if// ... 
int newsockfdd = whatever; 
// ... 
if (pthread_create(&threadID[i++], NULL, serverThread, &newsockfdd) != 0) 

주소는 newsockfdd입니다.

주의 사항 : serverThread이 여러 곳에서 호출되는 경우이 모든 장소의 통화를 수정해야합니다.

+0

main에서 로컬 변수의 주소를 매개 변수로 전달하는 것이 좋습니다. 이것은 serverThread()가 실행되기 전에 main이 종료되고 프로그램이 충돌 할 때 newsockfdd가 해제 될 것이므로 더 이상 유효한 주소가 아닌 주소를 역 참조하려고 시도하는 버그입니다. 중간 캐스트를 사용하거나 로컬 (로컬) 대신 정적 변수의 주소를 전달하는 것이 좋습니다. – davec

+0

흠, 나는'main'이 끝나면 모든 스레드가'pthread_create'd 쓰레드를 가지게됩니다. (하지만 어쨌든 생성 된 쓰레드에 합류해야합니다.) –

+0

나는 그것이 보장 될 것이라고 생각하지 않지만 잘못 될 수 있습니다. 어쨌든 미안보다 더 안전합니다. 스레드 생성이 main이라는 헬퍼 함수에서 수행되는지 고려하십시오. 그런 다음 주관청이 퇴장을 기다리는 지 여부와 관계없이 문제가 발생합니다. 그냥 엄지 손가락의 규칙으로, 다른 스레드에 로컬 주소를 전달하지 않는 것이 가장 좋습니다 ... – davec

관련 문제