访问进程环境变量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:
../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时的一个坑的更多相关文章
- python解释器的安装;python2与python3同时在环境变量中时的解决方案
新文档 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,addres ...
- Linux系统——访问U-BOOT环境变量
Linux系统下访问U-BOOT环境变量 移植过U-BOOT的人,都知道:在U-BOOT中存有ENV.但U-BOOT在引导内核启动之后,U-BOOT的生命周期就结束了.那么启动LINUX内核之后,U- ...
- 关于pyinstaller打包程序时设置icon时的一个坑
关于pyinstaller打包程序时设置icon时的一个坑 之前在用pyinstaller打包程序的时候遇到了关于设置图标的一点小问题,无论在后面加--icon 或是-i都出现报错.查了下st ...
- WSL Ubuntu 安装MongoDb 4.0导入公钥时遇到一个坑 (转)
WSL Ubuntu 安装MongoDb 4.0导入公钥时遇到一个坑 一路坑啊~~~网上的密钥都不对???? 不应该啊 源中默认是MongoDb 3.x 但是我想用4.0,然后按照mongodb官方 ...
- 进程的环境变量environ
编程之路刚刚开始,错误难免,希望大家能够指出. 每个进程都有自己的环境变量,在C语言程序中可使用外部变量(char **environ)来访问环境,而库函数可允许进程去获取或修改自己环境的值. 两种方 ...
- UNIX环境编程学习笔记(16)——进程管理之进程环境变量
lienhua342014-10-03 1 环境表和环境指针 在每个进程启动时,都会接到一张环境表.环境表是一个字符指针数组,其中每个指针包含一个以 null 结束的 C 字符串的地址.全局变量env ...
- 接口测试01- Jmeter-线程进程-环境变量
1.1 概念 JMeter 是 Apache 组织使用 Java 开发的一款测试工具 ,它最初被设计用于Web应用测试,但后来扩展到其他测试领域. 它可以用于测试静态和动态资源,例如静态文件.Java ...
- Web开发之tomcat配置及使用(环境变量设置及测试,一个简单的web应用实例)
Tomcat的配置及测试: 第一步:下载tomcat,然后解压到任意盘符 第二步:配置系统环境变量 tomcat解压到的D盘 (路径为: D:\tomcat), 配置环境变量: 启动tomcat需要两 ...
- Nginx 转发时的一个坑,运维居然让我背锅!!
最近遇到一个 Nginx 转发的坑,一个请求转发到 Tomcat 时发现有几个 http header 始终获取不到,导致线上出现 bug,运维说不是他的问题,这个锅我背了. 新增的几个 header ...
随机推荐
- vue请求本地json数据
1.下载vue-resource插件 cnpm install vue-resource 1.2全局引入vue-resource: 在main.js import VueResource from ' ...
- 037——VUE中表单控件处理之表单修饰符:lazy/number/trim
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 【小米oj】找出单独的数字
题目链接:https://code.mi.com/problem/list/view?id=2&cid=0&sid=26251#codearea 描述 给出N个数字.其中仅有一个数字出 ...
- wxpython的简单的应用
import wximport wx.xrc import pandas as pd from conf.env import * # 允许选择的文件wildcard = "Python s ...
- confluence 部署与配置
什么是confluence 部署步骤 安装 下载目标平台目标版本安装包.windows为例 若第一次默认安装 一直下一步. 若再次安装 下载并将mysql 连接控件放到 /xxx/xxx/conflu ...
- ElasticSearch6.0 索引模板
我们在做es搜索的场合,每次创建索引的时候,都需要为每个索引设置mapping的字段映射,现在我们可以为通用的索引创建一个模板 每次创建索引时候,如果匹配到相应的模板 索引的mapping会被自动设置 ...
- python3 堆排序
思路: 1.建立堆 2.得到堆顶元素,为最大元素 3.去掉堆顶,将堆最后一个元素放到堆顶,此时可通过一次调整重新使堆有序. 4.堆顶元素为第二大元素. 5.重复步骤3,直到堆变空. 动画 代码: de ...
- LeetCode OJ:Palindrome Partitioning(回文排列)
Given a string s, partition s such that every substring of the partition is a palindrome. Return all ...
- SpringInAction--自动化装配Bean(隐式装配)
关于Bean的介绍就具体不多介绍了,,, Spring在配置时候有三种方案可选 1.在xml中进行显示配置 2.在java中进行显示配置 3.隐式的Bean发现机制和自动装配 今天学习的就是自动化装配 ...
- Python中的数据结构 --- 列表(list)
列表(list)是Python中最基本的.最常用的数据结构(相当于C语言中的数组,与C语言不同的是:列表可以存储任意数据类型的数据). 列表中的每一个元素分配一个索引号,且索引的下标是从0开始. ...