什么是_REENTRANT标志?

时间:2010-04-08 16:38:38

标签: c++ c multithreading pthreads

编译多线程程序的

我们使用gcc,如下所示:

gcc -lpthread -D_REENTRANT -o someprogram someprogram.c

旗帜-D_REENTRANT到底在做什么?

5 个答案:

答案 0 :(得分:21)

定义_REENTRANT会导致编译器在C库中使用多个函数的线程安全(即可重入)版本。

您可以搜索头文件以查看定义后发生的情况。

答案 1 :(得分:4)

JayM回答说:

  

定义_REENTRANT会导致编译器在C库中使用多个函数的线程安全(即可重入)版本。

     

您可以搜索头文件以查看定义后发生的情况。

由于OP和我都对这个问题感兴趣,我决定实际发布答案。 :)在Mac OS X 10.11.6上_REENTRANT发生以下情况:

  • <math.h>获得lgammaf_rlgamma_rlgammal_r的声明。

在Linux(Red Hat Enterprise Server 5.10)上,我看到以下更改:

  • <unistd.h>获得POSIX 1995函数getlogin_r的声明。

所以似乎_REENTRANT现在大多数都是无操作者。它可能曾经宣布了许多新功能,例如strtok_r;但是现在这些功能大多是由几十年前的标准(C99,POSIX 95,POSIX.1-2001等)强制执行的,所以它们总是被启用。

我不知道为什么我检查的两个系统避免声明lgamma_r resp。当getlogin_r #defined时_REENTRANT。我的猜测是,这只是历史上的残余,没有人会费心去清理。

当然,我对这两个系统的观察可能不会推广到您的代码可能遇到的所有系统。当程序需要pthread时,你绝对应该将-pthread传递给编译器(或者,不太好,但没关系,-lpthread -D_REENTRANT)。

答案 2 :(得分:4)

摘录自libc 8.2 manual

  

宏:_REENTRANT
  巨集:_THREAD_SAFE

     

这些宏已过时。它们具有与定义相同的效果   _POSIX_C_SOURCE的值为199506L。

     

一些非常老的C库需要定义这些宏之一   使基本功能(例如getchar)具有线程安全性。

     

我们建议您在新程序中使用_GNU_SOURCE。如果您不指定   GCC的“ -ansi”选项或其他符合性选项,例如   -std = c99,并且没有明确定义任何这些宏,其效果与将_DEFAULT_SOURCE定义为1相同。

     

定义功能测试宏以请求更大类别的   功能,另外定义功能测试宏也无害   这些功能的子集。例如,如果您定义   _POSIX_C_SOURCE,然后定义_POSIX_SOURCE也无效。同样,如果定义_GNU_SOURCE,则定义   _POSIX_SOURCE或_POSIX_C_SOURCE也不起作用。

答案 3 :(得分:1)

它只是为预处理器定义了_REENTRANT。在相关代码中的某个位置,您可能会在至少几个位置找到#ifdef _REENTRANT#if defined(_REENTRANT)

另请注意,名称“_REENTRANT:在实施者的名称空间中(任何以下划线开头,后跟另一个下划线或大写字母的名称),因此定义它意味着您已超出标准定义的范围(在至少C或C ++标准。)

答案 4 :(得分:0)

在多线程程序中,您可以通过在程序中的任何#include行之前定义_REENTRANT宏来告诉编译器您需要此功能。这可以做三件事,而且做得非常优雅,通常您甚至不需要知道所做的事情:

  1. 某些函数获得可重入安全等效项的原型。 这些通常是相同的函数名,但在后面加上_r 例如,将gethostbyname更改为gethostbyname_r。
  2. 一些通常作为宏实现的stdio.h函数 成为适当的可重入安全功能。
  3. 将errno.h中的变量errno更改为调用函数, 可以以多线程安全的方式确定真正的errno值。

从开始进行Linux编程开始