访问进程环境变量environ时的一个坑
在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:204 204 ../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 15 if environ[i]==0
(gdb) p ptr $1 = 0x7fffffffefe3 "/home/xyz/TLPI/a.out" (gdb) p environ[i] $2 = 0x0
原因也清楚了。在C程序的存储空间高地址是命令行参数和环境变量依次排列,如下图
n1是环境变量的数量,n2是命令行参数的数量。因此在ptr指向最后一个环境变量时,ptr+=(strlen[ptr]+1)后指向的是argv[0]。
字符指针数组environ保存了n1+1个元素,多出一个元素是NULL。而ptr+=(strlen[ptr]+1)则是直接访问程序的存储空间,并没有一个终止符。
当ptr到达内存中不可访问的区域(即argv[n2-1]的下面,函数栈帧的地址),就会引发SIGSEGV信号。
转载于:https://www.cnblogs.com/Harley-Quinn/p/6817958.html
访问进程环境变量environ时的一个坑相关推荐
- 11g里创建OEM时的一个坑“emca -config dbcontrol db -repos recreate”
11g里创建OEM时的一个坑 关于11g的OEM的更多内容: http://blog.itpub.net/26736162/viewspace-2029565/ 关于Oracle里的组件说明: htt ...
- 【Linux】孤儿进程 | 环境变量 | 命令行参数 | 进程优先级
文章目录 1. 孤儿进程 2. 环境变量 1. PATH环境变量 证明ls是系统指令 修改自己写的可执行程序对应路径 2. env--查看系统环境变量 3. 获取环境变量 envp environ g ...
- jmeter进程和线程的区别_接口测试01- Jmeter-线程进程-环境变量
1.1 概念 JMeter 是 Apache 组织使用 Java 开发的一款测试工具 ,它最初被设计用于Web应用测试,但后来扩展到其他测试领域. 它可以用于测试静态和动态资源,例如静态文件.Java ...
- java 单元测试 私有成员变量,单元测试时测试一个private私有方法 - - ITeye博客
直接上例子 待测试的类 [code="java"]public class Calculator { private int count = 0; private int add( ...
- 环境变量environ
void getenviron(void) {extern char ** environ;char **pe= environ;while(*pe != NULL){cout<<*pe& ...
- 环境变量空格符号带来的坑
如图所示:设置环境变量: 环境变量对空格符号进行了截断:JAVA_HOME地址为c:\Program
- Kafka生产环境缩容遇到的一个坑
1.背景 最近在折腾Kafka日志集群,由于公司部署的应用不断增加,日志采集程序将采集到的日志发送到Kafka集群时出现了较大延迟,总的TPS始终上不去,为了不影响业务团队通过日志排查问题,采取了先解 ...
- 总结-linux初识进程(包括cpu调度、进程创建、僵尸进程(重点)、环境变量)
冯诺依曼体系结构--现代计算机的硬件体系结构 输入设备.输出设备(数据输出).存储器(数据缓冲).运算器(数据运算).控制器. 所有设备都是围绕存储器工作---CPU是从存储器中获取数据处理---控制 ...
- linux中的进程、环境变量和虚拟地址
目录 冯诺依曼体系结构 操作系统 进程概念 程序和进程 什么是程序 什么是进程 查看进程信息 进程.进程标识符&进程状态 进程创建 僵尸状态和僵尸进程 孤儿进程 环境变量 定义 常见的环境变量 ...
最新文章
- Kail Linux渗透测试教程之Recon-NG框架
- mysql udf http.so_MySQL-UDF-HTTP + Express + WebSocket 实现数据库推送
- Chrome浏览器查看SSL证书信息
- 蓝桥杯练习系统习题-算法训练2
- mysql 类型_MySQL-约束类型
- C#菜鸟正则表达式一
- 【转】谈谈Unicode编码,简要解释UCS、UTF、BMP、BOM等名词
- n个1组成的整数能被2013整除c语言,求大神解算法,“编写程序,求n至少为多大时,n个1组成的整数能被2013 整除。”...
- LSSS线性秘密共享方案详细构造方法与原理解释试读
- 使用 Hasor 从数据库查询显示到页面上
- “秃“如其来的植发经济是一门好生意吗?
- 透明壁纸android,主题透明壁纸软件下载-主题透明壁纸 安卓版v1.0-PC6安卓网
- DNA双螺旋结构是怎样发现的?
- Java从接触到放弃(二十一)--网络编程
- JAVA.SE JUnit单元测试 NIO
- ROS官网使用方式以及问题?
- 青铜到王者,京东数科这个AI机器人组织有多野?
- JavaScript谬论体系
- Python3 爬取 NBA 2013-2014 赛季比赛数据
- html_常用标签_盒子标签_图片标签_超链接_列表标签(2)
热门文章
- nginx有10个以上参数rewrite的处理
- MSSQL 判断表是否存在的两种方法
- visual stadio 添加 Extjs 智能提示!
- IBM技术大会2005
- 不要把时间画在抽奖上。。。去学习吧。。。
- U3D5.3.5f Monodevelop 仅支持到.NET 3.5
- jQuery-强大的jQuery选择器 (详解)
- webpack + react 使用 eslint
- 大数据创业难度大 五个值得关注的重点
- 【Spark Summit EU 2016】在在线学习中使用Structured Streaming流数据处理引擎