#ifdef用于32位平台

在我维护的应用程序中,我们遇到了影响stdlib的文件描述符限制的问题。 此问题仅影响标准库的32位版本。

我已经为我的代码设计了一个修复程序,并希望实现它,但只有在编译32位可执行文件时才能实现。 我可以#ifdef使用什么预处理器符号来确定是为32位还是64位目标编译代码?

编辑

对不起,没提,代码是跨平台,linux,windows,solaris和其他一些unix风格,大多使用GCC进行编译。 我可以跨平台使用任何事实上的标准吗?

编辑2

我发现了一些似乎可能有用的定义“__ILP23”和“__LP64”… 这里的讨论解释了unix平台的背景。 任何人都有使用这些定义的经验吗? 这有用吗?

我不确定是否有适合的通用#if def。 C ++标准几乎肯定没有定义一个。 虽然有一些平台的spcefic。

例如,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 

我建议为predef SourceForge添加书签。 没有一个答案,但它肯定可以帮助你开始。

编辑:对于仅GCC代码,您可以使用__i386__检查32位x86芯片,我建议尝试__X86_64__或类似的东西来检查64位x86芯片。 (注意:我注意到之前涉及__ia86__答案实际上是一个不同的芯片,而不是64位x86芯片。这只是表明我缺乏硬件经验。对于那些比我更了解硬件的人,请使用SourceForge我链接到上面的预定义宏的页面。它比我更准确。)还有一些其他的可行,但这两个应该是相当普遍的GCC版本。

看看:

i386宏
AMD64宏

您可以检查一个众所周知的类型,例如sizeof(int *)== 4,对于32位平台。

由于sizeof在编译时已知,我相信a

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

应该做的伎俩

编辑:评论是对的,你需要使用常规if,#if将无效。

如果您正在使用C ++您可以创建模板化代码,并让编译器根据sizeof()调用为您选择专门化。 如果构建32位平台,编译器只会实例化32位平台的代码。 如果构建654位平台,编译器将只实例化64位平台的代码。

我可能最终会做的,是在Makefile中,确定你是使用32位平台还是64位使用uname。 然后,添加到CFLAGS,-DX32或-DX64。 你可以#ifdef X64。

但这只是一个单一的解决方案。 我不确定我会在Windows上做什么。

至少32位Solaris具有256个文件指针的限制,因为该结构将文件描述符存储在unsigned char字段中。 保留这一点是为了向后兼容一些几乎不可能的旧版SunOS。 其他平台 – 我很想说大多数其他平台 – 不分享这个限制。 另一方面,普通用户程序需要同时打开多个文件是相对不常见的; 它通常表示一个错误(完成后不关闭文件)而不是。 尽管如此,对于需要同时打开大量数据文件的数据库服务器这样的问题可能会出现问题。


一条评论说:

差不多就是这样。 我们没有打开大量文件,但服务器处理来自客户端的大量连接。 套接字句柄和文件描述符似乎来自同一个地方。 当我们有很多连接时,’fopen’失败,因为系统级调用返回并且fd> 255。

“套接字句柄”是系统调用级别的文件描述符,因此它们来自与文件的常规文件描述符相同的位置。

如果你必须解决这个问题,那么你需要包装你当前的套接字开放代码,这样如果它获得0..255范围内的文件描述符,那么它调用’ dup2() ‘来创建一个范围内的文件描述符stdio将不会使用 – 然后关闭原始文件描述符。 唯一的障碍是你必须跟踪哪些文件描述符可用,因为dup2将在目前文件描述符当前打开的情况下快速关闭目标文件描述符。

当然,我假设您的套接字代码读取文件描述符而不是文件指针。 如果是这种情况,那么你就会遇到更大的问题 – 太多东西想要使用相同的资源而且他们不能同时使用它们。

取决于您的操作系统和编译器,这些是实现决策。

我在Windows中使用这样的结构:

 #if defined(_WIN64)
    // 64位代码
 #elif定义(_M_IX86)
    // 32位代码
 #其他
 #error“未知平台”
 #万一

与:

 #if defined(_WIN64)
   // 64位代码
 #其他
   // 32位代码
 #万一

在前一个解决方案中,由于#error,编译器将能够告诉您需要为新平台添加代码的位置。 如果您遇到既不是64位也不是32位的平台,这有助于可维护性。 是的,_M_IX86并不完全是32位的同义词,但我认为我们大多数人支持的唯一32位平台实际上是x86。 因此,作为一项实际措施,它就足够了。

在后面的解决方案中,您必须使用grep或类似的东西手动确定您需要新平台代码的位置。 这很乏味且容易出错。

在我看来,下面的结构也是可以接受的,虽然我没有在生产中测试它,也没有真正考虑过它。

 #if defined(_WIN64)
    // 64位代码
 #elif定义(_WIN32)
    // 32位代码
 #其他
 #error“未知平台”
 #万一

我相信定义是_WIN64

C ++标准没有定义这样的符号 – 您的特定平台(您在问题中未指定)可以提供一个。