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


я наткнулся на следующую задачку:

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

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

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

3 102

3 ответа:

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

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

The comp.ленг.с чаво есть запись обсуждаем зачем бросать возвращение из malloc никогда не нужен и потенциально плохо.

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

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

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

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

вот почему вы никогда не бросали возвращение Мэллока в C.

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

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