简体   繁体   English

#ifdef用于32位平台

[英]#ifdef for 32-bit platform

In an application I maintain, we've encountered a problem with file descriptor limitations affecting the stdlib. 在我维护的应用程序中,我们遇到了影响stdlib的文件描述符限制的问题。 This problem only affects the 32-bit version of the standard lib. 此问题仅影响标准库的32位版本。

I have devised a fix for my code and would like to implement it, but only when compiling for 32-bit executable. 我已经设计了一个修复我的代码,并希望实现它,但只有在编译32位可执行文件时。 What pre-processor symbol can I #ifdef for to determine whether the code is being compiled for a 32 or 64-bit target? 我可以#ifdef使用什么预处理器符号来确定是为32位还是64位目标编译代码?

EDIT 编辑

Sorry, didn't mention, the code is cross-platform, linux, windows, solaris and a few other unix flavors, mostly using GCC for compilation. 对不起,没提,代码是跨平台,linux,windows,solaris和其他一些unix风格,大多使用GCC进行编译。 Any de-facto standards I can use cross-platform? 我可以跨平台使用任何事实上的标准吗?

EDIT 2 编辑2

I've found some definitions "__ILP23" and "__LP64" that seem like they may work... a discussion here explains the background on the unix platform. 我发现了一些似乎可能有用的定义“__ILP23”和“__LP64”... 这里的讨论解释了unix平台的背景。 Anyone had any experience with using these defines? 任何人都有使用这些定义的经验吗? Is this going to be usable? 这会有用吗?

I'm not sure if there is a universal #if def that is appropriate. 我不确定是否有适合的通用#if def。 The C++ standard almost certainly does not define one. C ++标准几乎肯定没有定义一个。 There are certainly platform spcefic ones though. 虽然有一些平台的spcefic。

For example, Windows 例如,Windows

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

EDIT OP mentioned this is a cross compile between Windows and Non-Windows using GCC and other compilers EDIT OP提到这是使用GCC和其他编译器在Windows和非Windows之间进行交叉编译

There is no universal macro that can be used for all platforms and compilers. 没有可用于所有平台和编译器的通用宏。 A little bit of preprocessor magic though can do the trick. 一点点的预处理器魔术可以做到这一点。 Assuming you're only working on x86 and amd64 chips the following should do the trick. 假设您只使用x86和amd64芯片,以下应该可以解决问题。 It can easily be expanded for other platforms though 但是,它可以很容易地扩展到其他平台

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

I recommend bookmarking the predef SourceForge . 我建议为predef SourceForge添加书签。 There's no one answer, but it can certainly help you get started. 没有一个答案,但它肯定可以帮助你开始。

EDIT: For GCC-only code, you can use __i386__ to check for 32-bit x86 chips, and I suggest trying __X86_64__ or something similar to check for 64-bit x86 chips. 编辑:对于仅GCC代码,您可以使用__i386__检查32位x86芯片,我建议尝试__X86_64__或类似的东西来检查64位x86芯片。 (Note: It has come to my attention that the previous answer involving __ia86__ is actually a different chip, not a 64-bit x86 chip. This just shows my lack of hardware experience. For those more knowledgeable about hardware than I, consule the SourceForge page on predefined macros that I link to above. It's much more accurate than I am.) There are some other ones that would work, but those two should be fairly universal amongs GCC versions. (注意:我注意到之前涉及__ia86__答案实际上是一个不同的芯片,而不是64位x86芯片。这只是表明我缺乏硬件经验。对于那些比我更了解硬件的人,请使用SourceForge我链接到上面的预定义宏的页面。它比我更准确。)还有一些其他的可行,但这两个应该是相当普遍的GCC版本。

Have a look at that: 看看:

i386 macros i386宏
AMD64 macros AMD64宏

You could check a well known type for it's size eg sizeof(int*) == 4 for a 32 bit platform. 您可以检查一个众所周知的类型,例如,对于32位平台,sizeof(int *)== 4。

As sizeof is known at compiletime I believe a 由于sizeof在编译时已知,我相信a

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

should do the trick 应该做的伎俩

Edit: the comments are right, you need to use a regular if, #if won't work. 编辑:评论是对的,你需要使用常规if,#if将无效。

If you are using C++ You could create templated code and let the compiler choose the specialization for you based on the sizeof() call. 如果您正在使用C ++您可以创建模板化代码,让编译器根据sizeof()调用为您选择专门化。 If you build for a 32 bit platform the compiler would only instantiate the code for the 32 bit platform. 如果构建32位平台,编译器只会实例化32位平台的代码。 If you build for a 654 bit platform the compiler would only instantiate the code for the 64 bit platform. 如果为654位平台构建,则编译器将仅实例化64位平台的代码。

I would test it indirectly, via the maximum pointer value constant: 我会通过最大指针值常量间接测试它:

#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

This way you don't rely on any platform-specific define for architecture, but on the direct consequence of having a specific architecture - the pointer size. 这样,您不依赖于任何特定于平台的体系结构定义,而是依赖于具有特定体系结构的直接结果 - 指针大小。

What I would probably end up doing, is within a Makefile, determine if you are on a 32 bit platform or 64 bit using uname. 我可能最终会做的是,在Makefile中,确定你是使用uname还是32位平台或64位。 Then, add to your CFLAGS, -DX32, or -DX64. 然后,添加到CFLAGS,-DX32或-DX64。 That you could just #ifdef X64. 你可以#ifdef X64。

But this is just a unixy solution. 但这只是一个单一的解决方案。 I'm not sure what I would do on windows. 我不确定我会在Windows上做什么。

At least 32-bit Solaris has a limit of 256 file pointers because the structure stores the file descriptor in an unsigned char field. 至少32位Solaris具有256个文件指针的限制,因为该结构将文件描述符存储在unsigned char字段中。 This is retained for backwards compatibility with some almost impossibly old versions of SunOS. 保留这一点是为了向后兼容一些几乎不可能的旧版SunOS。 Other platforms - I'm tempted to say most other platforms - do not share that limitation. 其他平台 - 我很想说大多数其他平台 - 不会分享这个限制。 On the other hand, it is relatively unusual for an ordinary user program to need that many files open concurrently; 另一方面,普通用户程序需要同时打开多个文件是相对不常见的; it more often indicates a bug (not closing the files when finished with them) than not. 它通常表示一个错误(完成后不关闭文件)而不是。 Having said that, though, it can be a problem for things like database servers which need to have lots of data files open at the same time. 尽管如此,对于需要同时打开大量数据文件的数据库服务器这样的问题可能会出现问题。


One comment says: 一条评论说:

That's almost it. 差不多就是这样。 We don't have a large number of files open, but the server handles a large number of connections from clients. 我们没有打开大量文件,但服务器处理来自客户端的大量连接。 Socket handles and file descriptors seem to come from the same place. 套接字句柄和文件描述符似乎来自同一个地方。 When we have a lot of connections, 'fopen' fails because the system-level call returns and fd > 255. 当我们有很多连接时,'fopen'失败,因为系统级调用返回并且fd> 255。

'Socket handles' are file descriptors at the system call level, so they come from the same place as regular file descriptors for files. “套接字句柄”是系统调用级别的文件描述符,因此它们来自与文件的常规文件描述符相同的位置。

If you have to work around this, then you need to wrap your current socket opening code so that if it gets an file descriptor in the range 0..255, then it calls ' dup2() ' to create a file descriptor in the range that stdio won't use - and then close the original file descriptor. 如果你必须解决这个问题,那么你需要包装你当前的套接字开放代码,这样如果它获得0..255范围内的文件描述符,那么它调用' dup2() '来创建一个范围内的文件描述符该stdio将不会使用 - 然后关闭原始文件描述符。 The only snag with this is that you have to keep track of which file descriptors are available, because dup2 will merrily close the target file descriptor if it is currently open. 唯一的障碍是你必须跟踪哪些文件描述符是可用的,因为dup2将快速关闭目标文件描述符(如果它当前是打开的)。

Of course, I'm assuming your socket code reads file descriptors and not file pointers. 当然,我假设您的套接字代码读取文件描述符而不是文件指针。 If that's the case, you have bigger problems - too many things want to use the same resources and they can't all use them at the same time. 如果是这种情况,那么你就会遇到更大的问题 - 太多的事情想要使用相同的资源,并且他们不能同时使用它们。

I use a construction like this for Windows: 我在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

In the former solution, because of the #error the compiler will be able to tell you where you need to add code for a new platform. 在前一个解决方案中,由于#error,编译器将能够告诉您需要为新平台添加代码的位置。 This aids maintainability should you ever encounter a platform that is neither 64-bit nor 32-bit. 如果您遇到既不是64位也不是32位的平台,这有助于维护。 Yes, the _M_IX86 is not exactly synonymous with 32-bit, but I think the only 32-bit platform most of us are supporting is in fact x86. 是的,_M_IX86并不完全是32位的同义词,但我认为我们大多数人支持的唯一32位平台实际上是x86。 So as a practical measure it suffices. 因此,作为一项实际措施,它就足够了。

In the later solution you'll have to manually figure out where you need code for your new platform using grep or something like that. 在后面的解决方案中,您必须使用grep或类似的东西手动确定您需要新平台代码的位置。 This is tedious and error prone. 这很乏味且容易出错。

It occurs to me that the following construction would also be acceptable, although I have not tested it in production nor I have really thought about it very much. 在我看来,下面的结构也是可以接受的,虽然我没有在生产中测试它,也没有真正考虑过它。

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

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

我相信定义是_WIN64

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM