23

私が管理しているアプリケーションで、stdlibに影響を与えるファイル記述子の制限に関する問題が発生しました。この問題は、標準ライブラリの32ビットバージョンにのみ影響します。

私は自分のコードの修正を考案し、それを実装したいと思っていますが、32ビットの実行可能ファイル用にコンパイルする場合に限ります。コードが32ビットまたは64ビットのターゲット用にコンパイルされているかどうかを判断するために#ifdefで使用できるプリプロセッサシンボルは何ですか?

編集

申し訳ありませんが、コードはクロスプラットフォーム、Linux、Windows、Solaris、およびその他のいくつかのUNIXフレーバーであり、主にコンパイルにGCCを使用しています。クロスプラットフォームで使用できるデファクトスタンダードはありますか?

編集2

「__ILP23」と「__LP64」の定義が機能しているように見えることがあります...ここでの説明では、UNIXプラットフォームの背景について説明します。誰かがこれらの定義を使用した経験がありますか?これは使えるのでしょうか?

4

11 に答える 11

18

適切なユニバーサル#ifdefがあるかどうかはわかりません。C++標準はほぼ確実に1つを定義していません。ただし、プラットフォーム固有のものは確かにあります。

たとえば、Windows

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

EDIT OPは、これはGCCと他のコンパイラを使用したWindowsと非Windows間のクロスコンパイルであると述べました

すべてのプラットフォームとコンパイラに使用できるユニバーサルマクロはありません。プリプロセッサの魔法の少しは、トリックを行うことができますが。x86チップとamd64チップのみで作業していると仮定すると、次の方法でうまくいくはずです。ただし、他のプラットフォームにも簡単に拡張できます

#if _WIN64 || __amd64__
#define PORTABLE_64_BIT
#else
#define PORTABLE_32_BIT
#endif
于 2009-04-09T19:43:02.573 に答える
15

predefSourceForgeをブックマークすることをお勧めします。答えは1つではありませんが、それは確かにあなたが始めるのに役立ちます。

編集:GCCのみのコードの場合__i386__、32ビットx86チップのチェックに使用できます__X86_64__。64ビットx86チップのチェックなどを試してみることをお勧めします。(注:以前の回答__ia86__は、64ビットx86チップではなく、実際には別のチップであることに気付きました。これは、ハードウェアの経験が不足していることを示しています。私よりもハードウェアに精通している場合は、SourceForgeページを参照してください。上記にリンクしている事前定義されたマクロについて。私よりもはるかに正確です。)動作するマクロは他にもいくつかありますが、これら2つはGCCバージョン間でかなり普遍的である必要があります。

于 2009-04-09T19:45:02.460 に答える
6

それを見てください:

i386マクロ
AMD64マクロ

于 2009-04-09T19:53:51.050 に答える
6

最大ポインタ値定数を介して、間接的にテストします。

#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

このように、アーキテクチャのプラットフォーム固有の定義に依存するのではなく、特定のアーキテクチャを持つことの直接的な結果、つまりポインタサイズに依存します。

于 2019-01-16T17:13:25.887 に答える
5

よく知られているタイプのサイズを確認できます。たとえば、32ビットプラットフォームの場合はsizeof(int *)==4です。

sizeofはコンパイル時に知られているので、私は

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

トリックを行う必要があります

編集:コメントは正しいです。通常のif、#ifが機能しない場合は使用する必要があります。

C ++を使用している場合テンプレート化されたコードを作成し、sizeof()呼び出しに基づいてコンパイラーに特殊化を選択させることができます。32ビットプラットフォーム用にビルドする場合、コンパイラは32ビットプラットフォーム用のコードのみをインスタンス化します。654ビットプラットフォーム用にビルドする場合、コンパイラは64ビットプラットフォーム用のコードのみをインスタンス化します。

于 2009-04-09T19:43:02.840 に答える
2

私がおそらくやることになるのは、Makefile内で、32ビットプラットフォームを使用しているか、unameを使用して64ビットを使用しているかを判断することです。次に、CFLAGS、-DX32、または-DX64に追加します。#ifdefX64だけでいいのです。

しかし、これは単なる一義的な解決策です。Windowsで何をするかわかりません。

于 2009-04-09T19:51:58.760 に答える
2

構造体はファイル記述子をunsignedcharフィールドに格納するため、少なくとも32ビットのSolarisには256個のファイルポインタの制限があります。これは、ほとんど不可能なほど古いバージョンのSunOSとの下位互換性のために保持されています。他のプラットフォーム(他のほとんどのプラットフォームと言いたくなります)は、その制限を共有していません。一方、通常のユーザープログラムでは、多数のファイルを同時に開く必要があるのは比較的珍しいことです。多くの場合、バグ(終了時にファイルを閉じない)を示します。とはいえ、データベースサーバーのように、同時に大量のデータファイルを開く必要がある場合は問題になる可能性があります。


1つのコメントは言う:

それはほとんどそれです。開いているファイルの数は多くありませんが、サーバーはクライアントからの多数の接続を処理します。ソケットハンドルとファイル記述子は同じ場所から来ているようです。多くの接続がある場合、システムレベルの呼び出しが返され、fd> 255であるため、「fopen」は失敗します。

「ソケットハンドル」はシステムコールレベルのファイル記述子であるため、ファイルの通常のファイル記述子と同じ場所から取得されます。

これを回避する必要がある場合は、現在のソケットオープニングコードをラップして、0..255の範囲のファイル記述子を取得すると、' dup2()'を呼び出して、stdioが獲得した範囲のファイル記述子を作成する必要があります。 -を使用しないで、元のファイル記述子を閉じます。これに関する唯一の問題は、使用可能なファイル記述子を追跡する必要があることです。これはdup2、ターゲットファイル記述子が現在開いている場合は、ターゲットファイル記述子を陽気に閉じるためです。

もちろん、ソケットコードはファイルポインタではなくファイル記述子を読み取ると想定しています。その場合、より大きな問題が発生します。同じリソースを使用したいものが多すぎて、すべてを同時に使用することはできません。

于 2009-04-09T20:11:49.727 に答える
2

私はWindows用に次のような構造を使用しています。

#if defined(_WIN64)
   //64ビットコード
#elif defined(_M_IX86)
   //32ビットコード
#そうしないと
#error「不明なプラットフォーム」
#endif

対:

#if defined(_WIN64)
  //64ビットコード
#そうしないと
  //32ビットコード
#endif

前者のソリューションでは、#errorが原因で、コンパイラは新しいプラットフォームのコードを追加する必要がある場所を通知できます。これは、64ビットでも32ビットでもないプラットフォームに遭遇した場合の保守性を支援します。はい、_M_IX86は32ビットと完全に同義ではありませんが、私たちのほとんどがサポートしている32ビットプラットフォームは実際にはx86だけだと思います。したがって、実際的な対策としてはそれで十分です。

後者のソリューションでは、grepなどを使用して、新しいプラットフォームのコードが必要な場所を手動で把握する必要があります。これは面倒でエラーが発生しやすいです。

私は本番環境でテストしたことも、実際にそれについてあまり考えたこともありませんが、次の構造も許容できると思います。

#if defined(_WIN64)
   //64ビットコード
#elif defined(_WIN32)
   //32ビットコード
#そうしないと
#error「不明なプラットフォーム」
#endif
于 2011-07-23T13:33:32.597 に答える
1

OSとコンパイラによって異なりますが、これらは実装上の決定事項です。

于 2009-04-09T19:45:09.417 に答える
0

定義は_WIN64だと思います

于 2009-04-09T19:43:24.727 に答える
0

C ++標準で定義されているそのようなシンボルはありません。特定のプラットフォーム(質問で指定していない)がシンボルを提供する場合があります。

于 2009-04-09T19:45:29.010 に答える