2010-02-28 4 views
5

내 기능 : 메인에서in C : 스택 할당 구조가 함수 외부에 존재하는 이유는 무엇입니까?

struct hostent * gethost(char * hostname){ 
    if(/*some condition under which I want 
     to change the mode of my program to not take a host*/){ 
     return null 
    } 
    else{ 
     struct hostent * host = gethostbyname(hostname); 
     return host; 
    } 
} 

는 :

struct hostent * host = gethost(argv[2]); 

이 잘 작동 (I 메모리에서 분출하고있어 코드의 모든 사소한 오류를 무시). Valgrind는 내가 풀어주지 않은 사실에도 불구하고 기억을 잃어 가고 있다고 말하지 않습니다.

왜? 스택에 할당 된 항목이 함수 호출이 반환되면 사라지는 줄 알았지? 포인터를 반환했기 때문입니까? 이게 어떤면에서 위험한거야?

답변

10

host이 스택에 할당되지 않으면 스택에 대한 포인터 만 스택에 할당됩니다. 함수가 반환 될 때 포인터가 복사되므로 코드에 아무런 문제가 없습니다.

gethostbyname은 실제로 동적으로 메모리를 할당하지 않습니다. valgrind가 누출을보고하지 않는 이유는 항상 정적으로 할당 된 동일한 메모리 블록에 대한 포인터를 반환하기 때문입니다. 나중에 gethost을 호출하면 값을 덮어 쓰게되므로 나중에 값을 저장하려는 경우 함수에 의해 반환 된 hostent을 복사해야하므로주의해야합니다.

+0

아 감사합니다. 그래서 그것은'gethostbyname'에게 독특한 것입니까? 예를 들어'char *'에 대해 이렇게했다면, 그 배열의 값은 나중에 덮어 쓸 수 있습니까? 내 프로그램은 실행 당 하나의 호스트 만 처리해야하므로 잘되어야합니다. –

+0

나중에 호출 할 때 포인터가 가리키는 값이 덮어 쓰여 지는지 여부는 호출하는 함수에 따라 다릅니다. 전달하지 않는 포인터를 반환하는 C 표준 라이브러리 함수의 경우 정적 메모리에 대한 포인터를 반환하고 덮어 쓸 수 있다고 가정 할 수 있습니다. – Gabe

0

메모리에 대한 모든 참조가 손실 될 때까지 메모리가 누출되지 않습니다. 예를 들어, 포인터가 반환되므로 여전히 참조가 남아 있습니다.

그러나 대부분의 경우 동적 메모리를 해제하기 위해 코드의 다른 부분을 사용하는 것이 좋지 않습니다. 함수가 예를 들어 구조체를 반환해야하는 경우 호출자는이를 수행하고 구조체에 대한 포인터를 전달해야합니다. 수동에서

+2

'gethostbyname'이 동적 할당을하지 않기 때문에 메모리가 유출되지 않습니다. 매번 정적 포인터를 반환합니다. – Gabe

+2

누가이 포인터에 대한 참조를 추적합니까?:) – vladr

+2

아무도 포인터에 대한 참조를 추적하지 않습니다. 메모리 블록은 소켓 라이브러리가로드 될 때 할당되며 프로세스가 끝나거나 소켓 라이브러리가 언로드 될 때까지 할당이 취소되지 않습니다. – Gabe

2

:

RETURN VALUE 
     The gethostbyname() and gethostbyaddr() functions return the hostent 
     structure or a NULL pointer if an error occurs. On error, the h_errno 
     variable holds an error number. When non-NULL, the return value may 
     point at static data, ... 

일부 메모리가 컴파일 시간 (즉 바이너리 코드의 내부.) 구조에 대한 함수가이 메모리에 대한 포인터를 반환에 예약되어 있습니다.

3

반환 된 포인터가 스택 또는 힙의 데이터를 가리 키지 않지만 일부 정적 변수를 나타내므로 문제가 발생하지 않습니다.

http://linux.die.net/man/3/gethostbyname :

는 함수 gethostbyname까지도() 및이 gethostbyaddr는() 호출 이후 덮어 쓸 수 정적 데이터에 포인터를 리턴 할 수있다. struct hostent를 복사하는 것은 포인터를 포함하기 때문에 충분하지 않습니다. 깊은 사본이 필요합니다.

+0

왜 "글로벌"입니까? 전체적이고 정적 인 것은 같은 것이 아닙니다. – Ben

관련 문제