Почему этот код вызывает ошибку на 64-битной архитектуре, но отлично работает на 32-битной? - PullRequest
104 голосов
/ 25 сентября 2011

Я наткнулся на следующую загадку C:

В: Почему следующая ошибка программы на IA-64, но на IA-32 работает нормально?

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

Я знаю, что размер int на 64-битной машине может не совпадать с размером указателя (int может быть 32-битным, а указатель - 64-битным). Но я не уверен, как это относится к вышеуказанной программе. Есть идеи?

Ответы [ 3 ]

121 голосов
/ 25 сентября 2011

Приведение к int* маскирует тот факт, что без правильного #include тип возврата malloc предполагается равным int. IA-64 имеет sizeof(int) < sizeof(int*), что делает эту проблему очевидной.

(обратите внимание также, что из-за неопределенного поведения он может все еще не работать даже на платформе, где sizeof(int)==sizeof(int*) имеет значение true, например, если в соглашении о вызовах используются разные регистры для возврата указателей, чем целые числа)

В comp.lang.c FAQ есть запись, в которой обсуждается , почему приведение возврата из malloc никогда не нужно и потенциально плохо .

30 голосов
/ 25 сентября 2011

Скорее всего, потому что вы не включаете файл заголовка для malloc и, хотя компилятор обычно предупреждает вас об этом, тот факт, что вы явно приводите возвращаемое значение, означает, что вы 'повторяя это, вы знаете, что делаете.

Это означает, что компилятор ожидает, что int будет возвращен из malloc, который затем будет приведен к указателю.Если они разных размеров, это вызовет у вас горе.

Вот почему вы никогда не разыгрываете malloc возвращение в C. Возвращенное void* будет неявнопреобразован в указатель правильного типа (если только вы не включили заголовок, в этом случае он, вероятно, предупредил бы вас о потенциально небезопасном преобразовании типа int в указатель).

9 голосов
/ 25 сентября 2011

Вот почему вы никогда не будете компилировать без предупреждений об отсутствующих прототипах.

Именно поэтому вы никогда не приводите возвращение malloc в C.

Приведение необходимо для совместимости с C ++.Существует небольшая причина (читай: здесь нет причин), чтобы ее пропустить.

Совместимость с C ++ не всегда необходима, а в некоторых случаях вообще невозможна, но в большинстве случаев это очень легко достигается.

...