[c] 이 코드가 64 비트 아키텍처에서는 segfault이지만 32 비트에서는 잘 작동하는 이유는 무엇입니까?

다음 C 퍼즐을 발견했습니다.

Q : 다음 프로그램이 IA-64에서는 segfault를 실행하지만 IA-32에서는 제대로 작동하는 이유는 무엇입니까?

  int main()
  {
      int* p;
      p = (int*)malloc(sizeof(int));
      *p = 10;
      return 0;
  }

int64 비트 컴퓨터에서의 크기가 포인터의 크기와 같지 않을 수 있다는 것을 알고 int있습니다 (32 비트가 될 수 있고 포인터가 64 비트가 될 수 있음). 그러나 이것이 위의 프로그램과 어떤 관련이 있는지 잘 모르겠습니다. 어떤 아이디어?



답변

캐스트 int*는 적절한 #include반환 유형 malloc이없는 것으로 간주 된다는 사실 을 마스킹합니다 int. IA-64 sizeof(int) < sizeof(int*)는이 문제를 분명하게 만드는 일이 발생합니다.

( sizeof(int)==sizeof(int*)예를 들어 호출 규칙이 정수가 아닌 포인터를 반환하는 데 다른 레지스터를 사용하는 경우 와 같이 정의되지 않은 동작으로 인해 true를 유지 하는 플랫폼에서도 여전히 실패 할 수 있습니다. )

때 comp.lang.c 자주 묻는 질문은 토론 항목이 의 반환 캐스팅 이유를 malloc필요로하지 잠재적으로 나쁜 적이된다 .


답변

and에 대한 헤더 파일을 포함하지 않았기 때문에 malloc컴파일러가 일반적으로 이에 대해 경고하지만 반환 값을 명시 적으로 캐스팅한다는 사실은 수행중인 작업을 알고 있음을 의미합니다.

즉, 컴파일러는를 int반환 malloc한 다음 포인터로 캐스트 할 것으로 예상합니다 . 크기가 다르면 슬픔이 생길 것입니다.

이것이 C 에서 반환 을 절대 캐스팅 하지 않는 이유 malloc입니다. 반환되는 void*것은 올바른 유형의 포인터로 암시 적으로 변환됩니다 (헤더를 포함하지 않은 경우 잠재적으로 안전하지 않은 정수에 대해 경고했을 것입니다. 포인터로 변환).


답변

이것이 프로토 타입 누락에 대한 경고없이 컴파일하지 않는 이유입니다.

이것이 C에서 malloc 리턴을 결코 캐스팅하지 않는 이유입니다.

C ++ 호환성을 위해 캐스트가 필요합니다. 그것을 생략 할 이유가 거의 없습니다 (여기에 이유 없음).

C ++ 호환성이 항상 필요한 것은 아니며 일부 경우에는 전혀 불가능하지만 대부분의 경우 매우 쉽게 얻을 수 있습니다.


답변