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

#ifdef для 32-битной платформы

В приложении, которое я поддерживаю, мы столкнулись с проблемой ограничений файлового дескриптора, влияющих на stdlib. Эта проблема затрагивает только 32-разрядную версию стандартной библиотеки lib.

Я разработал исправление для своего кода и хотел бы его реализовать, но только при компиляции для 32-битного исполняемого файла. Какой символ препроцессора я могу указать #ifdef для определения того, компилируется ли код для 32 или 64-битной цели?

ИЗМЕНИТЬ

Извините, не упоминал, что код кросс-платформенный, linux, windows, solaris и несколько других unix-аксессуаров, в основном с использованием GCC для компиляции. Любые стандарты де-факто я могу использовать кросс-платформу?

РЕДАКТИРОВАТЬ 2

Я нашел некоторые определения "__ILP23" и "__LP64", которые, похоже, могут работать... обсуждение здесь объясняет предысторию на платформе unix. Кто-нибудь имел опыт использования этих определений? Это будет полезно?

4b9b3361

Ответ 1

Я не уверен, что есть универсальный #if def, который подходит. Стандарт С++ почти наверняка не определяет его. Конечно, есть платформы spcefic.

Например, Windows

#if _WIN64 
// 64 bit build
#else
// 32 bit build
#endif

EDIT OP упомянул, что это кросс-компиляция между Windows и Non-Windows с использованием GCC и других компиляторов

Нет универсального макроса, который может использоваться для всех платформ и компиляторов. Немного препроцессорной магии, хотя может сделать трюк. Предполагая, что вы работаете только с чипами x86 и amd64, следующее должно сделать трюк. Его можно легко расширить для других платформ, но

#if _WIN64 || __amd64__
#define PORTABLE_64_BIT
#else
#define PORTABLE_32_BIT
#endif

Ответ 2

Я рекомендую закладок predef SourceForge. Там нет ни одного ответа, но это, безусловно, поможет вам начать работу.

EDIT: для кода GCC вы можете использовать __i386__ для проверки 32-разрядных чипов x86, и я предлагаю попробовать __X86_64__ или что-то похожее на проверку 64-разрядных чипов x86. (Примечание. Мне пришло в голову, что предыдущий ответ с участием __ia86__ на самом деле является отличным чипом, а не 64-разрядным чипом x86. Это просто показывает отсутствие аппаратного обеспечения. Для тех, кто больше разбирается в аппаратных средствах, чем я, consule на странице SourceForge на предопределенных макросах, которые я ссылаюсь на выше. Это гораздо более точный, чем я.) Есть и другие, которые будут работать, но эти два должны быть довольно универсальными среди версий GCC.

Ответ 4

Вы можете проверить известный тип для этого размера, например. sizeof (int *) == 4 для 32-битной платформы.

Поскольку sizeof известен в compiletime, я считаю,

if(sizeof(int*) == 4)
{
  ...
}

должен сделать трюк

Изменить: комментарии правы, вам нужно использовать регулярное, если #if не будет работать.

Если вы используете С++, вы можете создать шаблонный код и позволить компилятору выбрать специализацию для вас на основе вызова sizeof(). Если вы создадите для 32-битной платформы, компилятор только создаст код для 32-битной платформы. Если вы создадите платформу размером 654 бит, компилятор только создаст код для 64-битной платформы.

Ответ 5

То, что я, вероятно, в конечном итоге сделаю, находится в Makefile, определите, находитесь ли вы на 32-битной платформе или 64-разрядной версии, используя uname. Затем добавьте в свои CFLAGS, -DX32 или -DX64. Это вы могли бы просто #ifdef X64.

Но это просто решение для unixy. Я не уверен, что делать с окнами.

Ответ 6

Как минимум 32-разрядная Solaris имеет ограничение в 256 указателей файлов, поскольку структура хранит дескриптор файла в неподписанном char поле. Это сохраняется для обратной совместимости с некоторыми почти невероятно старыми версиями SunOS. Другие платформы - я соблазн сказать большинство других платформ - не разделяю этого ограничения. С другой стороны, для обычной пользовательской программы относительно необычно, что многие файлы открываются одновременно; это чаще всего указывает на ошибку (не закрывая файлы, когда они заканчиваются с ними), чем нет. Сказав это, однако, это может быть проблемой для таких вещей, как серверы баз данных, которые должны иметь много файлов данных одновременно.


В одном комментарии говорится:

Это почти это. Мы не открываем большое количество файлов, но сервер обрабатывает большое количество подключений от клиентов. Ручки Socket и дескрипторы файлов, похоже, происходят из одного и того же места. Когда у нас много соединений, "fopen" терпит неудачу, потому что вызов системного уровня возвращается и fd > 255.

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

Если вам нужно обойти это, тогда вам нужно обернуть свой текущий код открытия сокета, чтобы, если он получает файловый дескриптор в диапазоне 0..255, он вызывает "dup2()" для создания файлового дескриптора в диапазоне, который stdio не будет использовать, - и затем закройте исходный дескриптор файла. Единственная проблема с этим заключается в том, что вам нужно отслеживать, какие файловые дескрипторы доступны, потому что dup2 будет весело закрывать дескриптор целевого файла, если он в настоящий момент открыт.

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

Ответ 7

Зависит от вашей ОС и компилятора, это решения по внедрению.

Ответ 8

Я использую такую ​​конструкцию для Windows:

#if defined(_WIN64)
   //64-bit code
#elif  defined(_M_IX86)
   //32-bit code
#else
#error "Unknown platform"
#endif

Versus:

#if defined(_WIN64)
  // 64 bit code
#else
  // 32-bit code
#endif

В первом решении из-за #error компилятор сможет рассказать вам, где вам нужно добавить код для новой платформы. Это помогает поддерживать работоспособность, если вы когда-либо сталкиваетесь с платформой, которая не является ни 64-разрядной, ни 32-разрядной. Да, _M_IX86 не совсем синоним 32-битного, но я думаю, что только 32-битная платформа, которую большинство из нас поддерживает, на самом деле является x86. Так что практической меры достаточно.

В более позднем решении вам придется вручную определить, где вам нужен код для вашей новой платформы, используя grep или что-то в этом роде. Это утомительно и подвержено ошибкам.

Мне кажется, что следующая конструкция также будет приемлемой, хотя я не тестировал ее в производстве, и я действительно очень об этом думал.

#if defined(_WIN64)
   //64-bit code
#elif  defined(_WIN32)
   //32-bit code
#else
#error "Unknown platform"
#endif

Ответ 9

Я считаю, что define - _WIN64

Ответ 10

Нет такого символа, который определен стандартом С++ - ваша конкретная платформа (которую вы не указали в своем вопросе) может предоставить один.

Ответ 11

Я бы протестировал это косвенно, через константу максимального значения указателя:

#include <stdint.h>

#if UINTPTR_MAX == 0xffFFffFF
// 32-bit platform
#elif UINTPTR_MAX == 0xffFFffFFffFFffFF
// 64-bit platform
#else
#error Unknown platform - does not look either like 32-bit or 64-bit
#endif

Таким образом, вы не полагаетесь ни на какое специфическое для платформы определение архитектуры, а на прямое следствие наличия конкретной архитектуры - размер указателя.