Подтвердить что ты не робот

Почему этот код segfault на 64-битной архитектуре, но отлично работает на 32-битной?

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

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

Ответ 3

Вот почему вы никогда не компилируете без предупреждения о пропавших прототипах.

Вот почему вы никогда не бросаете malloc return в C.

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

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