在静态初始化程序中(即在 main() 之前)使用 getenv() 是否安全?
-
22-07-2019 - |
题
我看了进去 史蒂文斯, ,并且在 Posix 程序员指南, ,我能找到的最好的是
称为的字符串数组 环境 当该过程开始时可用。该数组由外部变量指向
environ
, ,定义为:
extern char **environ;
就是那个 环境 让我犹豫的变量。我想说
- 调用进程/shell 已经分配了以 null 结尾的字符串块
-“外部”变量 environ
被用作入口点 获取环境().
-本身 欢迎致电 获取环境() 在静态初始值设定项内。
但我找不到任何保证“静态初始化” 环境 位于所有其他静态初始化代码之前。我是不是想太多了?
更新
在 我的 平台(AMD Opteron、Redhat 4、GCC 3.2.3)、设置 LD_调试 表明 环境 已设置 前 我的静态初始化器被调用。这是一件很高兴知道的事情;谢谢,@codelogic。但这不一定是我在所有平台上得到的结果。
另外,虽然我在 C/C++ 运行时库的行为上直观地同意@ChrisW,但这只是我基于经验的直觉。因此,任何可以引用权威人士的言论的人都可以保证 环境 在调用静态初始化器之前是否存在,加分!
解决方案
我认为你可以设置 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
您将看到 argc、argv 和 environ(别名为 __
environ)在调用任何全局构造函数(init 函数)之前设置。您可以从实际入口点 (start.S) _start 开始执行。正如你引用史蒂文斯的话 “当进程开始时,称为环境的字符串数组可用”, ,表明环境分配发生在进程初始化的一开始。这由链接器代码支持,其作用相同,应该让您足够安心:-)
编辑2: 另外值得一提的是,environ 设置得足够早,甚至运行时链接器也可以查询它以确定是否详细输出(LD_DEBUG)。
其他提示
鉴于这两个环境设置和静态初始化的调用是语言运行时必须执行的功能的前的main()函数调用,我不相信你会找到一个保证这里。也就是说,我不知道具体的要求,在这里,这的的的工作和该命令之前主要保证()的,也就是说,ANSI语言和库规范或什么... 。但我没有检查,以确保无论是。
与此同时,我不知道的,限制特定的要求,其运行时库函数可以从静态初始化调用。而且,更重要的是,它会觉得自己像一个运行时错误(对我来说),如果你不能从一个访问环境。
在此基础上,我投票,我希望它可以工作,是一个安全的假设,以及当前数据点似乎支持这样的推理。
在我的经验,C运行时库运行时调用你的静态变量的初始化之前进行初始化(因此你可以初始化调用C运行时库函数)。