Malloc의 결과를 던 졌습니까?


질문

 

이 질문에서, 누군가가 malloc의 결과를 던지지 않아야한다는 의견을 제시했다.I.E., 나는 이것을해야한다.

int *sieve = malloc(sizeof(*sieve) * length);

오히려 :

int *sieve = (int *) malloc(sizeof(*sieve) * length);

왜 그렇게 될까요?


답변

 

TL; 박사

int *sieve = (int *) malloc(sizeof(int) * length);

두 가지 문제가 있습니다.캐스팅 및 변수 대신 유형을 sizeOf에 대한 인수로 사용하고 있습니다.대신 이렇게하십시오.

int *sieve = malloc(sizeof *sieve * length);

긴 버전

아니요;결과를 던지지 마십시오.

void * 가이 경우 다른 포인터 유형으로 자동 및 안전하게 승격되므로 불필요합니다. 그것은 코드에 혼란을 첨가하고, 캐스팅은 매우 쉽게 읽을 수 없습니다 (특히 포인터 유형이 길면). 그것은 당신이 일반적으로 나쁜 자신을 반복합니다. 를 포함시키는 것을 잊어 버린 경우 오류를 숨길 수 있습니다.이로 인해 충돌이 발생할 수 있습니다 (또는 나중에 코드의 완전히 다른 부분에서 나중에 충돌이 발생하지 않아).포인터와 정수가 다르게 크기가 다르면 어떻게되는지 고려하십시오.그런 다음 캐스팅하여 경고를 숨기고 반품 주소의 비트를 잃을 수도 있습니다.참고 : C99 암시 적 기능이 C에서 사라졌으며 해결되지 않은 함수가 int를 반환한다는 자동 가정이 없기 때문에이 점은 더 이상 관련이 없습니다.

설명으로, "당신은 캐스팅 할 필요가 없습니까?"가 아니라 "당신은 캐스팅하지 않는다"고 말했습니다.제 의견으로는 캐스트를 포함하지 않아도 올바르게 알 수 있습니다.단순히 수행 할 수있는 이점이 없지만 잠재적 인 위험이 많으며 캐스트를 포함하여 위험에 대해 알지 못한다는 것을 나타냅니다.

또한 해설자가 지적하기 때문에 위의 대화는 C ++가 아닌 똑바로 C + +에 대해 이야기합니다.나는 C와 C ++를 별도의 언어로 확고하게 믿습니다.

추가를 추가하려면 코드는 오류를 일으킬 수있는 유형 정보 (int)를 반복하지 못합니다.반환 값을 저장하는 데 사용되는 포인터를 참조하는 것이 좋습니다.

int *sieve = malloc(length * sizeof *sieve);

이것은 또한 가시성을 증가시키기 위해 길이를 앞으로 이동하고 이중화 괄호를 sizeof로 떨어 뜨립니다.인수가 유형 이름 인 경우에만 필요합니다.많은 사람들이 이것을 알지 못하는 것처럼 보입니다 (또는 무시).기억하십시오 : sizeof는 기능이 아닙니다!:)


길이가 앞면까지 이사하는 동안 일부 드문 경우가 가시성을 높일 수 있습니다. 일반 경우에도 다음과 같이 표현을 작성하는 것이 좋습니다.

int *sieve = malloc(sizeof *sieve * length);

이 경우 sizeof를 유지하기 때문에 적어도 size_t 수학에서 곱셈을 수행합니다.

비교 : malloc (sizeof * sieve * length * 너비) 대 malloc (길이 * 너비 * sizeof * sieve) 너비와 길이가 size_t보다 작은 종류가 더 작은 경우 길이 * 너비를 오버플로 할 수 있습니다.



답변

C에서 malloc의 반환 값을 던질 필요가 없습니다.malloc에 의해 반환 된 void에 대한 포인터는 자동으로 올바른 유형으로 변환됩니다.그러나 코드가 C ++ 컴파일러로 컴파일되도록하려면 캐스트가 필요합니다.커뮤니티간에 선호되는 대안은 다음을 사용하는 것입니다.

int *sieve = malloc(sizeof *sieve * length);

또한 체형의 유형을 바꾸면 표현의 오른쪽 측면을 변경하는 것에 대해 걱정하지 않아도됩니다.

사람들이 지적한 것처럼 캐스팅이 나쁘다.특히 포인터 캐스트.



답변

당신은 캐스팅 할 필요가 있습니다.

C와 C ++ 사이에서 코드를 더 휴대 할 수있게 만들었으며, 그래서 경험을 통해 많은 프로그래머가 C ++ (또는 C와 로컬 컴파일러 확장자 ​​확장자)에 실제로 쓰는 경우 C에서 C에서 쓰는 것이 C에서 쓰는 것이 좋습니다. 그렇게하지 않으면 오류가 숨길 수 있습니다. Type * Type **을 작성할 때 혼란스러운 모든 예를 누르십시오. 적절한 헤더 파일이 트리의 숲을 그리워하지는 않음을 알지 못했습니다. "당신이 컴파일러를 보는 것에 대해 불평 할 것을 요청하지 못한 사실에 대해 걱정하지 마십시오. 그 pesky stdlib.h는 기억해야 할 진정한 중요한 일이라는 사실에 대해 걱정하지 마십시오!" 그것은 추가적인인지 교차 점검을 강제합니다. 그것은 해당 변수의 원시 크기를 위해 수행하는 산술 옆에 원하는 유형의 원하는 유형을 넣습니다. 나는 이렇게 할 수있는 이렇게 할 수 있다고 말하면서 malloc () 버그가 주조가있을 때 훨씬 더 빠르게 잡혔다는 것을 보여줍니다. 어설 션과 마찬가지로, 의도를 밝히는 주석은 버그를 줄입니다. 기계가 확인할 수있는 방식으로 자신을 반복하는 것은 종종 좋은 생각입니다. 실제로, 그것은 주장이 무엇인지, 그리고이 캐스트의 사용은 주장입니다. 어설 션은 여전히 ​​수년 전에 아이디어를 튜링으로 삼았으므로 코드를 올바르게 가져 오는 데 필요한 가장 일반적인 기술입니다.



답변

다른 사람들이 언급했듯이, C에는 필요하지 않지만 C ++에 필요합니다.C ++ 컴파일러로 C 코드를 컴파일하려고한다고 생각되면 다음과 같은 매크로를 사용할 수 있습니다.

#ifdef __cplusplus
# define NEW(type, count) ((type *)calloc(count, sizeof(type)))
#else
# define NEW(type, count) (calloc(count, sizeof(type)))
#endif

그런 식으로 당신은 여전히 매우 컴팩트 한 방식으로 그것을 작성할 수 있습니다.

int *sieve = NEW(int, 1);

또한 C 및 C ++에 대해 컴파일됩니다.



답변

Wikipedia에서 :

주조의 이점 캐스트를 포함하여 C 프로그램이나 기능을 C ++로 컴파일 할 수 있습니다. 주조는 원래 char *를 원래 반환 한 Malloc의 pre-1989 버전을 허용합니다. 캐스팅은 개발자가 대상 포인터 유형이 변경 될 경우 특히 포인터가 malloc () 호출에서 멀리 선언 된 경우 특히 목적지 포인터 유형이 변하지 않으면 (캐스팅을 요구하지 않고 그러한 동작을 경고 할 수 있음) 주조에 대한 단점 ANSI C 표준에서 캐스트는 중복됩니다. 캐스트를 추가하면 헤더 stdlib.h를 포함하지 않도록 마스크 할 수 있습니다. Malloc의 프로토 타입이 발견되는 A.가없는 경우 프로토 타입 Malloc의 경우 표준은 C 컴파일러를 필요로합니다. malloc이 int를 반환한다고 가정합니다. 캐스트가 없으면 경고가 있습니다 이 정수가 포인터에 할당되면 발행됩니다. 그러나, 캐스트,이 경고가 생성되지 않아 버그를 숨기고 있습니다. 특정에 아키텍처 및 데이터 모델 (예 : 64 비트 시스템에서 LP64, 여기서 길고 포인터는 64 비트이고 int는 32 비트입니다)이 오류는 암시 적으로 선언 된 것처럼 정의되지 않은 동작을 실제로 생성합니다. malloc은 실제로 정의 된 함수가 32 비트 값을 반환합니다. 64 비트 값을 반환합니다. 통행 규약 및 메모리에 따라 레이아웃, 이로 인해 스택이 스마트 될 수 있습니다. 이 문제는 덜 가능성이 적습니다 현대적인 컴파일러에서 눈에 띄지 않고 균일하게 생산할 때 미확인 된 기능이 사용 된 경고가 사용되므로 경고가 여전히 나타납니다. 예를 들어 GCC의 기본 동작은 다음과 같습니다. "호환되지 않는 암시 적 선언이 내장 된 내장형을 읽는 경고 함수 "캐스트가 존재하는지 여부에 관계없이. 선언에서 포인터의 유형이 변경되면 하나는 또한 malloc이 호출되고 캐스트되는 모든 라인을 변경해야합니다.

캐스팅이없는 Malloc이 선호되는 방법이 있고 가장 경험있는 프로그래머가 선택할 수 있지만 문제를 인식하는 것을 사용하는 것을 사용해야합니다.

I.E : C ++로 C 프로그램을 컴파일 해야하는 경우 (별도의 언어이지만) MALLOC의 결과를 캐스팅해야합니다.



답변

C에서 void 포인터를 다른 종류의 포인터로 암묵적으로 변환 할 수 있으므로 캐스트가 필요하지 않습니다.하나를 사용하면 캐주얼 관찰자가 필요로하는 이유가있는 이유가 있으며 오도 된 이유가있을 수 있습니다.

출처:https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc