C에서는 왜 포인터를 놓기 전에 던질까요?
오래된 코드 베이스에서 작업하고 있는데 free()를 호출할 때마다 거의 모든 인수에 캐스트를 사용합니다.예를들면,
free((float *)velocity);
free((float *)acceleration);
free((char *)label);
여기서 각 포인터는 대응하는(및 일치하는) 유형입니다.나는 이것을 하는 것이 전혀 의미가 없다고 본다.아주 오래된 코드라서 K&R 같은 건 아닌지 의문이 남아요.이 경우 이전 컴파일러를 지원하고 싶기 때문에 삭제하고 싶지 않습니다.
이 깁스를 사용해야 하는 기술적 이유가 있습니까?나는 그것들을 사용할 실용적인 이유조차 잘 모르겠다.데이터를 해방하기 직전에 데이터 유형을 상기하는 것이 무슨 의미가 있습니까?
편집: 이 질문은 다른 질문과 중복되지 않습니다.또 다른 질문은 이 질문의 특별한 경우인데, 저는 가까운 유권자들이 모든 답을 읽을 수 있다면 분명하다고 생각합니다.
콜로폰:이것이 필요한 진짜 이유이기 때문에 "const answer" 체크 마크를 붙입니다.하지만, 적어도 일부 프로그래머들 사이에서는 ANSI C 이전의 커스텀이라고 하는 답변이 제 경우에 사용된 이유인 것 같습니다.여기 많은 분들이 좋은 점들이 많네요.당신의 노고에 감사드립니다.
포인터가 다음과 같은 경우 컴파일러 경고를 해결하기 위해 캐스팅이 필요할 수 있습니다.const
다음은 free 인수를 제시하지 않고 경고를 발생시키는 코드의 예입니다.
const float* velocity = malloc(2*sizeof(float));
free(velocity);
컴파일러(gcc 4.8.3)는 다음과 같이 말합니다.
main.c: In function ‘main’:
main.c:9:5: warning: passing argument 1 of ‘free’ discards ‘const’ qualifier from pointer target type [enabled by default]
free(velocity);
^
In file included from main.c:2:0:
/usr/include/stdlib.h:482:13: note: expected ‘void *’ but argument is of type ‘const float *’
extern void free (void *__ptr) __THROW;
사용하시는 경우free((float*) velocity);
컴파일러가 불평을 멈춘다.
이전 표준 C에는 없었다.void*
다만char*
전달된 모든 파라미터를 캐스팅해야 했습니다.고대 C 코드를 발견하면 이러한 캐스트를 찾을 수 있습니다.
참고문헌과 비슷한 질문입니다.
첫 번째 C 표준이 출시되었을 때, malloc 및 free의 프로토타입은 malloc 및 free의 시제품에서 변경되었습니다.char*
에게void*
아직도 가지고 있는 것 같아요
물론 표준 C에서는 이러한 깁스는 불필요하며 가독성을 해칠 뿐입니다.
여기 또 다른 가설이 있다.
이 프로그램은 C89보다 전에 작성되었다고 합니다.즉, 이 프로그램은 C89의 프로토타입과 일치하지 않습니다.free
왜냐하면, 그런 것이 없었을 뿐만 아니라const
도 아니다void *
C89 이전에는 기능 프로토타입이 없었습니다. stdlib.h
그 자체가 위원회의 발명품이었다.시스템 헤더가 일부러 선언한 경우free
이런 식으로 했을 거예요.
extern free(); /* no `void` return type either! */
여기서 중요한 점은 함수 프로토타입이 없다는 것은 컴파일러가 인수유형체크를 하지 않았다는 것입니다.디폴트 인수 프로모션(바리안트 함수 호출에 적용되는 것과 동일)이 적용되어 이것으로 끝입니다.각 콜 사이트의 주장을 착신측의 기대와 일치시키는 책임은 전적으로 프로그래머에게 있습니다.
하지만, 이것은 여전히 논쟁할 필요가 있었다는 것을 의미하지는 않는다.free
대부분의 K&R 컴파일러에 탑재되어 있습니다.와 같은 기능
free_stuff(a, b, c)
float *a;
char *b;
int *c;
{
free(a);
free(b);
free(c);
}
올바르게 컴파일 되어 있어야 합니다.그래서 여기 있는 것은 버그가 많은 컴파일러에 대응하기 위해 작성된 프로그램이라고 생각합니다.예를 들어 다음과 같은 특수한 환경입니다.sizeof(float *) > sizeof(int)
그리고 컴파일러는 콜 포인트로 적절한 호출 규칙을 사용하지 않는 한 포인터 규칙을 사용하지 않습니다.
저는 그런 환경에 대해 전혀 알지 못하지만 그렇다고 해서 그런 환경이 없었던 것은 아닙니다.1980년대 초 8비트 및 16비트 마이크로용 "타이니 C" 컴파일러가 가장 유력하게 떠오릅니다.초기 크레이가 이런 문제를 겪었다는 사실도 놀랍지 않을 것이다.
오래된 이유: 1.사용방법free((sometype*) ptr)
, 포인터를 의 일부로 간주할 필요가 있는 타입에 대해서는, 코드가 명시되어 있습니다.free()
명시적 캐스트는, 다음의 경우에 도움이 됩니다.free()
(Do-it-Resign)로 대체됩니다.DIY_free()
.
#define free(ptr) DIY_free(ptr, sizeof (*ptr))
A DIY_free()
(특히 디버깅모드에서) 해방된 포인터의 런타임 분석을 실행하는 방법이었습니다.이것은 많은 경우,DIY_malloc()
credential, 글로벌 메모리 사용량 카운트 등을 추가합니다.우리 팀은 더 현대적인 도구가 등장하기 전에 이 기술을 몇 년 동안 사용했습니다.그것은 free'd가 유형으로 주조된 항목이 원래 할당되었다는 것을 의무화했다.
- 메모리 문제 등을 추적하는 데 오랜 시간이 걸리기 때문에 type free'd를 캐스팅하는 등의 작은 트릭을 사용하면 디버깅을 검색하고 좁힐 수 있습니다.
모던: 회피const
그리고.volatile
경고는 Manos Nikolaidis@ 및 @egur에 의해 해결되었습니다.세 가지 예선의 효과를 주목해야겠다고 생각했습니다.const
,volatile
,그리고.restrict
.
[편집] 추가char * restrict *rp2
per @R.. 코멘트
void free_test(const char *cp, volatile char *vp, char * restrict rp,
char * restrict *rp2) {
free(cp); // warning
free(vp); // warning
free(rp); // OK
free(rp2); // warning
}
int main(void) {
free_test(0,0,0,0);
return 0;
}
다음은 깁스를 하지 않으면 무료가 실패할 수 있는 예입니다.
volatile int* p = (volatile int*)malloc(5 * sizeof(int));
free(p); // fail: warning C4090: 'function' : different 'volatile' qualifiers
free((int*)p); // success :)
free((void*)p); // success :)
C에서는 경고를 받을 수 있습니다(VS2012에서는 경고를 받았습니다).C++에서는 에러가 발생합니다.
드문 케이스는 차치하고, 캐스팅은 코드를 부풀릴 뿐이고...
편집: 캐스팅 대상void*
것은 아니다.int*
에러를 데모합니다. 하면 됩니다.int*
will will will will will will 로 변환됩니다.void*
★★★★★★★가 추가되었습니다.int*
free는 상수 이외의 포인터만 파라미터로 가져옵니다.따라서 const 포인터의 경우 non-const 포인터에 대한 명시적 캐스팅이 필요합니다.
언급URL : https://stackoverflow.com/questions/34019977/in-c-why-do-some-people-cast-the-pointer-before-freeing-it
'programing' 카테고리의 다른 글
Vuex를 사용하여 양식 입력 데이터를 변경할 수 없음 (0) | 2022.06.05 |
---|---|
EAGAIN이 무슨 뜻이죠? (0) | 2022.06.05 |
계산된 값에서 Vue.js의 v-for 값을 합산하는 방법 (0) | 2022.06.05 |
keytool 오류 Keystore가 조작되었거나 암호가 잘못되었습니다. (0) | 2022.06.05 |
vuelidate 참/거짓 확인 (0) | 2022.06.04 |