13

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

当进程开始时,一个称为环境的字符串数组可用。该数组由外部变量 指向,environ定义为:

extern char **environ;

正是那个环境变量让我犹豫不决。我想说

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

- 'external' 变量被getenv()environ用作入口点。

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

但是我找不到任何保证environ的“静态初始化”在所有其他静态初始化代码之前。这是我想太多了吗?

更新

我的平台(AMD Opteron、Redhat 4、GCC 3.2.3)上,设置LD_DEBUG表明在调用我的静态初始化程序之前设置了environ 。这是一件好事。谢谢,@codelogic。但这不一定是我在所有平台上都能得到的结果。

此外,虽然我直观地同意@ChrisW 关于 C/C++ 运行时库的行为,但这只是我基于经验的直觉。因此,任何可以从某个权威的地方引用来保证环境在调用静态初始化程序之前就在那里的人,加分!

4

3 回答 3

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/elf/start.S

您将看到 __在调用任何全局构造函数(init 函数)之前设置了 argc、argv 和 environ(environ 的别名)。您可以从 _start(实际入口点 (start.S))开始跟踪执行。正如您引用史蒂文斯所说的“当进程开始时,一个称为环境的字符串数组可用”,这表明环境分配发生在进程初始化的最开始。这由链接器代码支持,它做同样的事情,应该给你足够的安心:-)

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

于 2009-01-12T22:38:29.627 回答
4

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

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

在此基础上,我投票认为我希望这会奏效,这是一个安全的假设,并且当前的数据点似乎支持这种推理。

于 2009-01-13T01:13:40.967 回答
1

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

于 2009-01-12T22:37:07.100 回答