在静态初始化器中使用getenv()是否安全,即在main()之前?

时间:2009-01-12 22:32:35

标签: c++ c unix posix environment

我查看StevensPosix Programmer's Guide,我能找到的最好的是

  

进程开始时,可​​以使用名为环境的字符串数组。   外部变量environ指向此数组,其定义为:

     

extern char **environ;

这是 environ 变量让我犹豫不决。我想说

- 调用进程/ shell已经分配了空终止字符串块

- '外部'变量environ getenv()用作入口点。

- ipso facto 随时可以在静态初始化程序中调用 getenv()

但我无法保证 environ 的'静态初始化'优先于所有其他静态初始化代码。我是否想过这个?

更新

我的平台(AMD Opteron,Redhat 4,GCC 3.2.3)上,设置 LD_DEBUG 表示 environ 已设置之前调用我的静态初始值设定项。这是一个很好的事情要知道;谢谢,@ codelogic。但这并不一定是我在所有平台上得到的结果。

此外,虽然我直观地同意@ChrisW关于C / C ++运行时库的行为,但这只是我基于经验的直觉。因此,任何能够在静态初始化程序之前使用来自某个地方权威保证 environ 的报价的人都会被称为奖励积分!

3 个答案:

答案 0 :(得分:8)

我认为您可以使用LD_DEBUG设置运行程序以查看确切的顺序:

LD_DEBUG=all <myprogram>

修改 如果查看运行时链接程序的源代码(glibc 2.7),特别是在文件中:

  • sysdeps / UNIX / SYSV / LINUX / INIT-first.c
  • sysdeps / I386 / INIT-first.c
  • CSU / libc的-start.c
  • sysdeps / I386 /精灵/ start.S中

您将看到argc,argv和environ(__ environ的别名)在调用任何全局构造函数(init函数)之前设置。您可以从_start(实际入口点(start.S))开始执行。正如你引用Stevens “当进程开始时,可​​以使用称为环境的字符串数组”,这表明环境分配在进程初始化的最初阶段发生。这由链接器代码支持,它也可以让您充分放心: - )

编辑2:另外值得一提的是,environ设置得足够早,即使运行时链接器也可以查询它以确定是否要详细输出(LD_DEBUG)。

答案 1 :(得分:4)

鉴于环境设置和静态初始化程序的调用都是语言运行时必须在调用 main()之前执行的函数,我不确定您是否会找到保证这里。也就是说,我不知道这个工作的特定要求,并且在main()之前保证顺序,例如ANSI语言和库规范或任何东西......但我也没有检查确定。

同时,我不知道限制哪些运行时库函数可以从静态初始化程序调用的特定要求。而且,更重要的是,如果您无法从一个环境访问环境,那么对我来说就像是一个运行时错误。

在此基础上,我投票表示我希望这可行,是一个安全的假设,当前的数据点似乎支持这种推理。

答案 2 :(得分:1)

根据我的经验,在运行时调用静态变量的初始化程序之前初始化C运行时库(因此初始化程序可能会调用C运行时库函数)。