gcc -D_REENTRANT 到底做了什么?
What does gcc -D_REENTRANT really do?
我正在为 C 库编写 Java 绑定,因此使用 JNI。 Oracle specifies,合理地,与 Java 一起使用的本机库应该使用支持多线程的编译器进行编译。
JNI 文档给出了具体示例,对于 gcc
,应通过定义宏 _REENTRANT
或 _POSIX_C_SOURCE
之一来满足此多线程感知要求。这对我来说似乎很奇怪。 _REENTRANT
和 _POSIX_C_SOURCE
是功能测试宏。 GCC 和 POSIX 文档描述了它们在定义符号和使声明可见方面的效果,正如我对任何功能测试宏所期望的那样。
如果我不需要额外的符号或功能,那么这些宏实际上对我有什么用吗?一个或两个会导致 gcc
生成与其他情况下不同的代码吗?它们是否可能导致我的代码对标准库函数的调用链接到不同的实现?还是 Oracle 只是在谈论它的阴暗区域?
编辑:
此外,我想到重入是独立于线程的考虑因素。即使对于单线程程序,不可重入也可能是一个问题,因此 Oracle 关于定义 _REENTRANT
使 gcc
多线程感知的建议现在看起来更加可疑。
Oracle 推荐是为 Solaris 而写的,而不是为 Linux。
在 Solaris 上,如果您在没有 _REENTRANT
的情况下编译 .so
并最终被多线程应用程序加载,那么可能会发生非常糟糕的事情(例如 libc 内部的随机数据损坏)。这是因为如果没有定义,默认情况下您最终会使用某些例程的未锁定变体。
我第一次阅读此文档时就是这种情况,大概是 15 年前,在我上次详细阅读此文档后添加了 sun studio 编译器的 -mt
标志的提及。
情况不再如此 - 无论您是否使用 _REENTRANT
标志进行编译,您现在总是得到相同的例程;它现在只是一个功能宏,而不是行为宏。
我正在为 C 库编写 Java 绑定,因此使用 JNI。 Oracle specifies,合理地,与 Java 一起使用的本机库应该使用支持多线程的编译器进行编译。
JNI 文档给出了具体示例,对于 gcc
,应通过定义宏 _REENTRANT
或 _POSIX_C_SOURCE
之一来满足此多线程感知要求。这对我来说似乎很奇怪。 _REENTRANT
和 _POSIX_C_SOURCE
是功能测试宏。 GCC 和 POSIX 文档描述了它们在定义符号和使声明可见方面的效果,正如我对任何功能测试宏所期望的那样。
如果我不需要额外的符号或功能,那么这些宏实际上对我有什么用吗?一个或两个会导致 gcc
生成与其他情况下不同的代码吗?它们是否可能导致我的代码对标准库函数的调用链接到不同的实现?还是 Oracle 只是在谈论它的阴暗区域?
编辑:
此外,我想到重入是独立于线程的考虑因素。即使对于单线程程序,不可重入也可能是一个问题,因此 Oracle 关于定义 _REENTRANT
使 gcc
多线程感知的建议现在看起来更加可疑。
Oracle 推荐是为 Solaris 而写的,而不是为 Linux。
在 Solaris 上,如果您在没有 _REENTRANT
的情况下编译 .so
并最终被多线程应用程序加载,那么可能会发生非常糟糕的事情(例如 libc 内部的随机数据损坏)。这是因为如果没有定义,默认情况下您最终会使用某些例程的未锁定变体。
我第一次阅读此文档时就是这种情况,大概是 15 年前,在我上次详细阅读此文档后添加了 sun studio 编译器的 -mt
标志的提及。
情况不再如此 - 无论您是否使用 _REENTRANT
标志进行编译,您现在总是得到相同的例程;它现在只是一个功能宏,而不是行为宏。