캐스트 프리의 반환 값을 무효로하는 이유는 무엇입니까?


82

C를 사용 하는 책 ( POSIX Threads by Butenhof, 1997)을 읽고 있는데 다음 줄을 보았습니다.

(void)free(data);

여기, data할당 된 구조체에 대한 포인터입니다.

data = malloc(sizeof(my_struct_t));

결과 free가 캐스트 된 이유는 무엇 void입니까?

C에 대한 나의 이해에서 이것은 두 가지 이유로 이해되지 않는 것 같습니다.

  • 자유 함수는 이미 반환 void
  • 코드가 반환 값을 사용하지 않습니다 (변수에도 할당되지 않음)

이 책은 1997 년에 썼습니다. 이것은 일종의 유산입니까?

필자는 예제가 Digital Unix 4.0d에서 실행되었다고 언급하지만 그 결과를 사용하지 않을 경우 함수 결과를 캐스트해야 할 이유를 여전히 상상할 수 없습니다.


가능한 설명은 여기에 있습니다 : stackoverflow.com/questions/689677/…
Timbo

3
호기심으로 C 책의 출판 날짜는 얼마입니까? (이것이 어느 책입니까?) 1995 년 이전에는 표준 C 컴파일러가 그 어느 때보 다 편재하지 않았습니다. 그 이후에 출판되었지만 여전히 캐스트가 포함되어 있고 (이유에 대한 설명이없는 경우) 다른 나쁜 습관이 당신을 가르치고 있는지 걱정하십시오. 더 최근의 책을 얻으십시오!
Jonathan Leffler


3
내 원래 게시물에 언급 된 @JonathanLeffler는 1997 년에 출판되었으며 UNIX 4.0d를 사용하고있었습니다. 이 책은 David R. Butenhof의 "POSIX 스레드 프로그래밍"입니다. 지금까지는 매우 유익했으며 POSIX 스레드 표준의 원래 기고자 중 한 사람이 작성했습니다.
Adam Johnston

6
지난 주에이 사본을 사용했습니다. 그래도 여전히 유용합니다. 그것은 '유비쿼터스 표준 C'(나는 '약 1995'라고 말함)의 단서에 쓰여졌습니다. 'UNIX 4.0d'는 부텐 호프가 일했던 곳인 디지털 유닉스처럼 들리며 서문에서 언급합니다. free()책에서 에뮬레이션 할 필요가없는 이상한 것으로 캐스팅을 취급하십시오 . 옛날 옛적에 반쯤 관련이 있었지만 더 이상 관련이 없습니다.
Jonathan Leffler

답변:


100

우리가 표준 free기능 에 대해 이야기한다면 프로토 타입은

void free(void *ptr);

따라서 캐스트는 완전히 쓸모가 없습니다.
이제 몇 가지 추측.

작성자 stdlib.h가이 프로토 타입을 선언 하는 헤더 를 포함하지 않았을 수 있으므로 컴파일러는 리턴 유형을로 가정합니다 int. 이제이 코드를 정적 분석하는 동안 컴파일러는 void함수 가 아닌 것으로 생각되는 것의 사용되지 않은 반환 값에 대해 경고했습니다 . 이러한 경고는 일반적으로에 캐스트를 추가하여 침묵합니다 void.


50
그러나 추측 된 이유로 캐스트가 도입 된 경우 캐스트를 사용하여 경고를 끄는 것은 올바르지 않습니다 . 이 경우 컴파일러는 free호출이 정의되지 않은 동작을 갖는 결과 (실제로 선언되지 않은 함수를 호출하는 것이 모든 경우에 UB를 나타내지 않는 C90 의미론을 가짐)와 다른 유형을 실제와 다른 것으로 표시합니다. 실제로, 일부 시스템 에서는 선의의 오작동 이 발생할 가능성이 높습니다 . 올바른 해결책은 함수에 대한 올바른 선언을 제공하는 것입니다.
John Bollinger

11
특히 "POSIX 스레드 프로그래밍"의 예제에는 관련 표준 헤더가 반복적으로 포함되지 않습니다. 어쩌면 이것은 저자의 나쁜 습관 일 수 있었으며 기본적으로 모든 표준 라이브러리를 포함하는 비표준 컴파일러 설정을 사용했을 수 있습니다.
Lundin

74

레거시 일 것입니다!

C 표준이 있기 전에는 free()함수가 (암시 적으로) 타입이었을 것입니다. int왜냐하면 void반환 할 타입이 아직 확실하지 않기 때문 입니다. 값이 반환되지 않았습니다.

표준 C 컴파일러에서 작동하도록 코드를 처음 수정했을 때는 포함되지 않았을 가능성이 높습니다 (표준보다 코드가 <stdlib.h>존재하지 않았기 때문). 오래된 코드를 작성합니다 extern char *malloc();(아마없이 extern할당 기능 (유사에 대한) calloc()realloc()), 및 선언에 필요하지 않았다 free(). 그리고 코드는 반환 값을 올바른 유형으로 캐스팅합니다. 왜냐하면 적어도 일부 시스템 (필자가 C를 배운 시스템 포함)에서 필요했기 때문입니다.

언젠가, (void)캐스트는 불만을 피하기 위해 lint"의 리턴 값 free()이 의도적으로 무시된다"고 컴파일러에게 알리기 위해 추가되었다 . 그러나 <stdlib.h>선언을 선언 하거나 컴파일러에게 무시할 가치가 없다고 extern void free(void *vp);알리는 것이 더 좋을 것 lint입니다.

JFTR : 80 년대 중반, ICL Perq는 원래 단어 중심 아키텍처에 있었고 char *메모리 위치 의 주소는 'anything_else 포인터'와 같은 위치와는 매우 다른 숫자였습니다. char *malloc()어떻게 든 선언하는 것이 중요했습니다 . 결과를 다른 포인터 유형으로 캐스트하는 것이 중요했습니다. 캐스트는 실제로 CPU가 사용하는 숫자를 변경했습니다. (시스템의 메인 메모리가 1MiB에서 2MiB로 업그레이드되었을 때 많은 기쁨이있었습니다. 커널이 약 3 / 4MiB를 사용했기 때문에 사용자 프로그램은 페이징 등을하기 전에 1 1 / 4MiB를 사용할 수있었습니다.)


9
방금 K & R, 1 판의 사본을 열었습니다 free(). 177 암시 적으로 반환합니다 int.
전 니힐로

9
물론 – void표준이 발표되기 전에 일부 시스템 (Unix System III)에 추가되었지만 K & R 1st Edn (1978)이 작성되었을 때 C의 일부는 아니 었습니다. 값을 반환하지 않은 함수는 반환 유형없이 선언되었으므로 (반환 된 의미 int) 반환 되지 않은 값을 사용하지 않는 한 문제가 없었습니다. C90 표준은 이러한 종류의 코드를 유효한 것으로 취급해야했습니다. 표준이 아니었을 때 실제로는 실패했을 것입니다. 그러나 C99는 '암시 적 int'및 '암시 적 함수 선언'규칙을 제거했습니다. 세계의 모든 코드가 따라 잡지는 않았습니다.
Jonathan Leffler

5
Op는이 책이 1997 년에 작성되었다고 주장합니다. 여러분이 여기서 말하는 것은 매우 초기의 사전 표준 "K & R C"이며, 아무도 그것에 대해 책을 쓰지 않을 것 같습니다. 내가 아는 유일한 책은 실제로 K & R 1st edition이었습니다.
Lundin

암시 적 선언으로 벗어날 수 있다고 생각되면 헤더를 포함하지 않는 것이 빈번한 (빠른 경우라면) 관행이었습니다. 사람들은 그것이 빌드 시간을 단축 할 것이라고 생각했기 때문입니다.
스펜서

아무도 (void)캐스트를 사용합니까 printf()??
Luis Colorado

11

이 캐스트는 필요하지 않습니다. C가 C89 형식으로 표준화 되었기 때문에 아마도 당시에는 없었을 것입니다.

그랬다면 암시 적 선언 때문일 것 입니다. 이것은 일반적으로 코드를 작성하는 사람이 잊어 버렸고 #include <stdlib.h>정적 분석기가 사용되고 있음을 의미했습니다. 이것은 가장 좋은 해결 방법이 아니며 훨씬 더 나은 아이디어가 #include <stdlib.h>대신 되었을 것입니다. 암시 적 선언에 대한 C89의 문구는 다음과 같습니다.

함수 호출에서 괄호로 묶은 인수 목록 앞에 오는 표현식이 식별자로만 구성되어 있고이 식별자에 대한 선언이 표시되지 않으면 함수 호출을 포함하는 가장 안쪽 블록에서 선언처럼 정확하게 식별자가 암시 적으로 선언됩니다.

extern int identifier();

나타났다.

그들은 결과 캐스팅하지 않을 때문에 그러나 그것은 이상한 malloc중 하나를, 그리고 mallocfree같은 헤더 파일에 있습니다.

이것은 단지 실수이거나 독자에게 free결과 를 반환하지 않는다고 알려주는 방법 일 수도 있습니다.


5
언어가 표준화되었다고해서 모든 사람이 즉시 툴체인과 코드를 업데이트하여 해당 언어를 준수한다는 의미는 아닙니다. 구식 "K & R"C가 또 다른 8 년 동안 갇힌 것이 그럴듯하다. 그러나 정적 분석 도구가에 대한 캐스트가 필요 free하지만별로 필요 하지 않다는 것에 동의합니다 malloc.
dan04

4
@ dan04 당신은 일반적으로 malloc의 결과를 사용합니다;) 나는 컴파일러의 경고를 멈추기 위해 (void) printf (...)와 같은 것을 쓰는 팬이 아니지만 "어떤 경고없이 컴파일해야합니다, 어리석은 경고조차도" 많은 프로젝트에서 발생합니다.
richardb
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.