1、envp
注:并不是所有的系统中都有这种扩展,所以在考虑程序的可移植性的时候最好不要使用他.
因为在 C99中只有两种合法的main函数定义:
int main(int argc, char *argv[]);//argc 表示启动参数个数, argv保存了各个参数的内容
int main();
main函数还有一种定义方式:
int main(int argc, char *argv[], char *envp[]);
其中envp表示环境变量,形式为<name=value>,且地址在argv之后
演示代码:
#include<Windows.h>
#include<iostream>
using namespace std;
int main(int argc,char* argv[], char* envp[]) {
for (int i = 0; envp[i] != NULL; i++) {
cout << " envp[" <<i<<"] ==> " << envp[i] << endl;
}
system("pause");
}
输出:
envp[0] ==> ALLUSERSPROFILE=C:\ProgramData
envp[1] ==> APPDATA=C:\Users\user\AppData\Roaming
envp[2] ==> CommonProgramFiles=C:\Program Files\Common Files
envp[3] ==> CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files
envp[4] ==> CommonProgramW6432=C:\Program Files\Common Files
envp[5] ==> COMPUTERNAME=DESKTOP-RA2Q1K1
envp[6] ==> ComSpec=C:\WINDOWS\system32\cmd.exe
envp[7] ==> COR_ENABLE_PROFILING=1
envp[8] ==> COR_PROFILER={e30ed54c-76d6-493e-aaf4-881c84d367e2}
envp[9] ==> COR_PROFILER_PATH=C:\Users\user\AppData\Local\Temp\aIzssyzwarUkD.dll
envp[10] ==> DriverData=C:\Windows\System32\Drivers\DriverData
envp[11] ==> ENABLE_XAML_DIAGNOSTICS_SOURCE_INFO=1
envp[12] ==> FPS_BROWSER_APP_PROFILE_STRING=Internet Explorer
envp[13] ==> FPS_BROWSER_USER_PROFILE_STRING=Default
envp[14] ==> HOMEDRIVE=C:
envp[15] ==> HOMEPATH=\Users\user
envp[16] ==> LOCALAPPDATA=C:\Users\user\AppData\Local
...
请按任意键继续. . .
在Windows中envp的地址在argv后面,但argv的大小在程序启动时长度已经固定。所以在替换argv的值过长时,会出现内存越界,越界写了不该写的内存区域。
在Linux中envp的地址在argv后面,且替换argv的值过长时会影响envp的值
Windows替换演示:
#define _CRT_SECURE_NO_WARNINGS //忽略警告
#include<Windows.h>
#include<iostream>
int main(int argc,char* argv[], char* envp[]) {
strcpy(argv[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
for (int i = 0; envp[i] != NULL; i++) {
cout << " envp[" <<i<<"] ==> " << envp[i] << endl;
}
system("pause");
}
错误:
0x00007FFC1BB2F609 (ntdll.dll) (Project.exe 中)处有未经处理的异常: 0xC0000374: 堆已损坏。 (参数: 0x00007FFC1BB997F0)。
Linux替换演示:
#include <cstdio>
#include <cstring>
int main(int argc, char *argv[], char *envp[]) {
strcpy(argv[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
for (int i = 0; envp[i] != NULL; i++) {
cout << " envp[" <<i<<"] ==> " << envp[i] << endl;
}
}
输出:
envp[0] ==> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
envp[1] ==> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
envp[2] ==> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
envp[3] ==> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
envp[4] ==> xxxxxxxxxxxxxxxxxxxx
envp[5] ==> xxxx
envp[6] ==> SSH_CLIENT = 192.168.2.3 54187 51
envp[7] ==> SELINUX_USE_CURRENT_RANGE =
envp[8] ==> ANDROID_NDK_TOOLCHAIN_ROOT = / root / smaug / software / android - ndk - r16b / toolchains
envp[9] ==> OLDPWD = / root
envp[10] ==> SSH_TTY = / dev / pts / 1
envp[11] ==> USER = root
2、getenv() 函数
返回一个以null结尾的字符串,该字符串为被请求环境变量的值。如果该环境变量不存在,则返回 NULL
定义:
char *getenv(const char *name);
使用:
#define _CRT_SECURE_NO_WARNINGS //忽略警告
#include<Windows.h>
#include<iostream>
using namespace std;
int main(int argc,char* argv[], char* envp[]) {
char* i = getenv("PATH");//被请求变量名称的字符串PATH
cout << i << endl;
system("pause");
}
输出:
D:\bin\;
C:\WINDOWS\system32;
C:\WINDOWS;C:\WINDOWS\System32\Wbem;
C:\WINDOWS\System32\WindowsPowerShell\v1.0\;
C:\WINDOWS\System32\OpenSSH\;
C:\Program Files\dotnet\;C:\Users\user\AppData\Local\Microsoft\WindowsApps;
C:\Users\user\.dotnet\tools
请按任意键继续. . .
3、extern char **environ (Linux)
使用:
#include<stdio.h>
extern char **environ;
int main()
{
for(i = 0; *environ[i]; i++){
printf("*environ[%d]: %s\n", i, environ[i]);
}
}
输出:
*environ[0]: ORBIT_SOCKETDIR=/tmp/orbit-root
*environ[1]: SSH_AGENT_PID=3432
*environ[2]: GPG_AGENT_INFO=/tmp/seahorse-I1EsFP/S.gpg-agent:3493:1
*environ[3]: TERM=xterm
*environ[4]: SHELL=/bin/bash
*environ[5]: XDG_SESSION_COOKIE=4f027cabadbf93d36492b7424b4a1694-1264793154.856694-819590398
*environ[6]: GTK_RC_FILES=/etc/gtk/gtkrc:/root/.gtkrc-1.2-gnome2
*environ[7]: WINDOWID=65074553
*environ[8]: GTK_MODULES=canberra-gtk-module
*environ[9]: USER=root
*environ[10]: GNOME_KEYRING_SOCKET=/tmp/keyring-NBsJ8W/socket
*environ[11]: SSH_AUTH_SOCK=/tmp/ssh-cvNttB3314/agent.3314
*environ[12]: SESSION_MANAGER=local/h180:/tmp/.ICE-unix/3314
*environ[13]: USERNAME=root
*environ[14]: DESKTOP_SESSION=default
...