在unistd.h中定义了变量char **environ;来表示当前所有环境变量,一般来说访问特定环境变量可以用getenv,但是想遍历所有环境变量就得使用environ。

即在程序内全局声明extern char **environ;当然设定main函数第3个参数也可以,不过不推荐,因为ISO C的main函数没有第三个参数。

environ维护了一个char*数组,每个元素都是一个指针指向函数栈帧顶部的环境变量,数组结尾是NULL。

于是正确的遍历姿势是下面这样

    for (int i = 0; environ[i] != NULL; i++)
puts(environ[i]);

然后我试了下错误的姿势

	for (char *ptr = environ[0]; ptr; ptr++)
puts(ptr);

结果是程序dump了,审查了下发现错误出在ptr++上,因为ptr类型是char*,执行++后指针只向前移动1 byte。

于是就变成这样

	for (char *ptr = environ[0]; ptr; ptr += (strlen(ptr) + 1)
puts(environ[i]);

代码已经比较丑陋了,而且还多出了不必要的计算,即strlen函数,但是程序依然dump了。

我的调试方式是这样的

    for (char *ptr = environ[0]; ptr; ptr += (strlen(ptr) + 1))
{
static int i = 0;
if (strcmp(ptr, environ[i]) != 0)
{
printf("error: %d\n", i);
break;
}
puts(ptr);
i++;
}

错误如下

Program received signal SIGSEGV, Segmentation fault.
__strcmp_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S:
../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S: No such file or directory.

对啊,environ数组最后一个元素是NULL,但是strcmp必须接收非NULL指针作为参数(因为strcmp的参数s1、s2必须可以用*s1、*s2来访问,NULL是地址0,是用户无法访问的地址,用户访问无法访问的地址时就会产生SIGSEGV信号)。

于是我定位到了strcmp这句

(gdb) b  if environ[i]==
(gdb) p ptr
$ = 0x7fffffffefe3 "/home/xyz/TLPI/a.out"
(gdb) p environ[i]
$ = 0x0

原因也清楚了。在C程序的存储空间高地址是命令行参数和环境变量依次排列,如下图

n1是环境变量的数量,n2是命令行参数的数量。因此在ptr指向最后一个环境变量时,ptr+=(strlen[ptr]+1)后指向的是argv[0]。

字符指针数组environ保存了n1+1个元素,多出一个元素是NULL。而ptr+=(strlen[ptr]+1)则是直接访问程序的存储空间,并没有一个终止符。

当ptr到达内存中不可访问的区域(即argv[n2-1]的下面,函数栈帧的地址),就会引发SIGSEGV信号。

访问进程环境变量environ时的一个坑的更多相关文章

  1. python解释器的安装;python2与python3同时在环境变量中时的解决方案

    新文档 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,addres ...

  2. Linux系统——访问U-BOOT环境变量

    Linux系统下访问U-BOOT环境变量 移植过U-BOOT的人,都知道:在U-BOOT中存有ENV.但U-BOOT在引导内核启动之后,U-BOOT的生命周期就结束了.那么启动LINUX内核之后,U- ...

  3. 关于pyinstaller打包程序时设置icon时的一个坑

    关于pyinstaller打包程序时设置icon时的一个坑     之前在用pyinstaller打包程序的时候遇到了关于设置图标的一点小问题,无论在后面加--icon 或是-i都出现报错.查了下st ...

  4. WSL Ubuntu 安装MongoDb 4.0导入公钥时遇到一个坑 (转)

    WSL Ubuntu 安装MongoDb 4.0导入公钥时遇到一个坑 一路坑啊~~~网上的密钥都不对????  不应该啊 源中默认是MongoDb 3.x 但是我想用4.0,然后按照mongodb官方 ...

  5. 进程的环境变量environ

    编程之路刚刚开始,错误难免,希望大家能够指出. 每个进程都有自己的环境变量,在C语言程序中可使用外部变量(char **environ)来访问环境,而库函数可允许进程去获取或修改自己环境的值. 两种方 ...

  6. UNIX环境编程学习笔记(16)——进程管理之进程环境变量

    lienhua342014-10-03 1 环境表和环境指针 在每个进程启动时,都会接到一张环境表.环境表是一个字符指针数组,其中每个指针包含一个以 null 结束的 C 字符串的地址.全局变量env ...

  7. 接口测试01- Jmeter-线程进程-环境变量

    1.1 概念 JMeter 是 Apache 组织使用 Java 开发的一款测试工具 ,它最初被设计用于Web应用测试,但后来扩展到其他测试领域. 它可以用于测试静态和动态资源,例如静态文件.Java ...

  8. Web开发之tomcat配置及使用(环境变量设置及测试,一个简单的web应用实例)

    Tomcat的配置及测试: 第一步:下载tomcat,然后解压到任意盘符 第二步:配置系统环境变量 tomcat解压到的D盘 (路径为: D:\tomcat), 配置环境变量: 启动tomcat需要两 ...

  9. Nginx 转发时的一个坑,运维居然让我背锅!!

    最近遇到一个 Nginx 转发的坑,一个请求转发到 Tomcat 时发现有几个 http header 始终获取不到,导致线上出现 bug,运维说不是他的问题,这个锅我背了. 新增的几个 header ...

随机推荐

  1. 004-对象——public protected private PHP封装的实例

    <?php /** *public protected private PHP封装的实例 */ /*class tv { private $shengyin; function __constr ...

  2. 二十一、utl_file(用于读写OS文件)

    1.概述 作用:用于读写OS文件.使用该包访问OS文件时,必须要为OS目录建立相应的DIRECTORY对象..当用户要访问特定目录下的文件时,必须要具有读写DIRECTORY对象的权限.在使用UTL_ ...

  3. RabbitMQ(5) 事务&生产者确认

    事务&生产者确认 一般情况下,生产者将消息发送后,继续进行别的业务逻辑处理.消息从生产者发送后,可能由于网络原因丢失,也可能因为RabbitMQ服务端奔溃未被处理...总之,对于 消息是否安全 ...

  4. iOS二维码、条形码生成(可指定大小、颜色)

    一.前言: iOS7.0之后可以利用系统原生 API 生成二维码, iOS8.0之后可以生成条形码, 系统默认生成的颜色是黑色. 在这里, 利用以下方法可以生成指定大小.指定颜色的二维码和条形码, 还 ...

  5. 网络请求工具 cURL

    网络请求工具 cURL 2017-08-16 cRUL 是一种命令行工具,作用是发出网络请求,然后得到和提取数据,显示在“标准输出”(stdout)上面. 查看网页源码 1 $ curl baidu. ...

  6. TreeSet实现原理及源码分析

    类似于HashMap和HashSet之间的关系,HashSet底层依赖于HashMap实现,TreeSet底层则采用一个NavigableMap来保存TreeSet集合的元素.但实际上,由于Navig ...

  7. java.lang.IllegalArgumentException: Invalid character found in method name

    1.错误描述 信息: Error parsing HTTP request header Note: further occurrences of HTTP header parsing errors ...

  8. sql server 插入用户

    '创建登陆用户 use master create login [mashenghao] with password='kline',DEFAULT_DATABASE=[kchnetdb], DEFA ...

  9. stark组件02

    1.怎么在显示页面添加新字段(a标签)?在admin.py下注册就好了 当我们需要在admin页面添加新的a标签时,需要引入一个类似safe功能的模块 from django.utils.safest ...

  10. 数据库备份mysqldump

    |--好友说:有些知识就是石头,走上这条路就没法绕过,就是牙齿啃碎了也要把它啃下来. ------------------------------------------ 针对当前备份做一个总结记忆: ...