我的代码在 Linux 上给出了环境变量

My code gives out Environment variables on Linux

有些代码可能没有任何意义,(也许我也很困惑)这是怎么发生的,为什么? 这段代码是为了其他目的,(我试图制作一个计算器,所以主要源代码 [几乎没有问题] 作为我的问题存在于这个网站上)我以某种方式破坏了它所以我修改了它并提取了代码最初打破了它。

我在 Kali 上测试过 Linux。

代码如下:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

//Some of this might not make any sense, but its the way i was able to break it.. somehow
int main(int argc,char *argv[]) {
    FILE *file = fopen(argv[2],"a");
    if(file == NULL) {
        printf("Error Opening File!");
        return 1;
    }
    char ch;
    int i;
    printf("%i\n",argc);
    printf("%i\n",argv);
    while((ch = getopt(argc,argv,"d:"))!=EOF)
        switch(ch) {
        case 'd':
            for(i=4; i<=48; i++) // This loop may vary on other system. On first run i used "i<=51" , and on different system, same os, its the mentioned condition
                fprintf(file,"%s \n",argv[i]);
            fclose(file);
            break;
        default:
            fprintf(stderr,"No such command");
        }
    argc-=1;
    argv+=1;


    return 0;
}

以下结果是在 运行(原始源代码。此代码将其写入文件)上产生的:

value at argv= LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:.tar=01;31:.tgz=01;31:.arc=01;31:.arj=01;31:.taz=01;31:.lha=01;31:.lz4=01;31:.lzh=01;31:.lzma=01;31:.tlz=01;31:.txz=01;31:.tzo=01;31:.t7z=01;31:.zip=01;31:.z=01;31:.Z=01;31:.dz=01;31:.gz=01;31:.lrz=01;31:.lz=01;31:.lzo=01;31:.xz=01;31:.zst=01;31:.tzst=01;31:.bz2=01;31:.bz=01;31:.tbz=01;31:.tbz2=01;31:.tz=01;31:.deb=01;31:.rpm=01;31:.jar=01;31:.war=01;31:.ear=01;31:.sar=01;31:.rar=01;31:.alz=01;31:.ace=01;31:.zoo=01;31:.cpio=01;31:.7z=01;31:.rz=01;31:.cab=01;31:.wim=01;31:.swm=01;31:.dwm=01;31:.esd=01;31:.jpg=01;35:.jpeg=01;35:.mjpg=01;35:.mjpeg=01;35:.gif=01;35:.bmp=01;35:.pbm=01;35:.pgm=01;35:.ppm=01;35:.tga=01;35:.xbm=01;35:.xpm=01;35:.tif=01;35:.tiff=01;35:.png=01;35:.svg=01;35:.svgz=01;35:.mng=01;35:.pcx=01;35:.mov=01;35:.mpg=01;35:.mpeg=01;35:.m2v=01;35:.mkv=01;35:.webm=01;35:.ogm=01;35:.mp4=01;35:.m4v=01;35:.mp4v=01;35:.vob=01;35:.qt=01;35:.nuv=01;35:.wmv=01;35:.asf=01;35:.rm=01;35:.rmvb=01;35:.flc=01;35:.avi=01;35:.fli=01;35:.flv=01;35:.gl=01;35:.dl=01;35:.xcf=01;35:.xwd=01;35:.yuv=01;35:.cgm=01;35:.emf=01;35:.ogv=01;35:.ogx=01;35:.aac=00;36:.au=00;36:.flac=00;36:.m4a=00;36:.mid=00;36:.midi=00;36:.mka=00;36:.mp3=00;36:.mpc=00;36:.ogg=00;36:.ra=00;36:.wav=00;36:.oga=00;36:.opus=00;36:.spx=00;36:.xspf=00;36:

value at argv= XDG_MENU_PREFIX=gnome-

value at argv= LANG=en_IN

value at argv= GDM_LANG=en_IN

value at argv= MANAGERPID=793

value at argv= DISPLAY=:1

value at argv= INVOCATION_ID=3e7f771adfde4001af637f9527e9cc9d

value at argv= COLORTERM=truecolor

value at argv= USERNAME=root

value at argv= XDG_VTNR=2

value at argv= SSH_AUTH_SOCK=/run/user/0/keyring/ssh

value at argv= S_COLORS=auto

value at argv= XDG_SESSION_ID=3

value at argv= USER=root

value at argv= DESKTOP_SESSION=gnome

value at argv= PWD=/media/root/F89AF7139AF6CCDE

value at argv= HOME=/root

value at argv= JOURNAL_STREAM=9:19456

value at argv= SSH_AGENT_PID=945

value at argv= QT_ACCESSIBILITY=1

value at argv= XDG_SESSION_TYPE=x11

value at argv= XDG_DATA_DIRS=/usr/share/gnome:/usr/local/share/:/usr/share/

value at argv= XDG_SESSION_DESKTOP=gnome

value at argv= DBUS_STARTER_ADDRESS=unix:path=/run/user/0/bus,guid=11c587e1337f9fb06858c2415bbac73a

value at argv= GTK_MODULES=gail:atk-bridge

value at argv= WINDOWPATH=2

value at argv= TERM=xterm-256color

value at argv= SHELL=/bin/bash

value at argv= VTE_VERSION=5002

value at argv= DBUS_STARTER_BUS_TYPE=session

value at argv= XDG_CURRENT_DESKTOP=GNOME

value at argv= GPG_AGENT_INFO=/run/user/0/gnupg/S.gpg-agent:0:1

value at argv= SHLVL=1

value at argv= XDG_SEAT=seat0

value at argv= LANGUAGE=en_IN:en

value at argv= WINDOWID=39845894

value at argv= GDMSESSION=gnome

value at argv= GNOME_DESKTOP_SESSION_ID=this-is-deprecated

value at argv= LOGNAME=root

value at argv= DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus,guid=11c587e1337f9fb06858c2415bbac73a

value at argv= XDG_RUNTIME_DIR=/run/user/0

value at argv= XAUTHORITY=/run/user/0/gdm/Xauthority

value at argv= PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

value at argv= SESSION_MANAGER=local/kali:@/tmp/.ICE-unix/894,unix/kali:/tmp/.ICE-unix/894

value at argv= _=./a.out

value at argv= (null)

我接下来的问题是,环境变量到底是什么?为什么我会给我这样的结果?

// probably use one option at a time
//This code has some flaws, for example i didnt check if the file was opened 
or not, etc, pardon me for it. This is the actual un-edited source of the 
code.

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

int add(int a,int b){
return a+b;
}

int subtract(int a, int b){
return a-b;
}

int main(int argc, char *argv[]){
FILE *file1 = fopen("Results.txt","a");
char ch;
int res;
while((ch=getopt(argc,argv,"a:s:"))!=EOF)
    switch (ch){
        case 'a':
            res = add(atoi(optarg),atoi(argv[3]));
            fprintf(file1,"%i\n",res);
            break;
        case 's':
            res = subtract(atoi(optarg),atoi(argv[3]));
            printf("%i \n",res);
            fprintf(file1,"%i\n",res);
            break;
        default:
            fprintf(stderr,"No such option");
            return 1;

    }
//THe commented out section produces weird behaviour...

//printf("Opind = %i, argc = %i, argv = %i \n",optind,argc,argv);

argc-=optind;

//printf("value at optarg = %i value at argv_3= %s \n",optarg,argv[3]);

argv+=optind;

//printf("Opind = %i, argc = %i, argv = %i \n",optind,argc,argv);

//printf("value at optarg = %i value at argv_3= %s \n",optarg,argv[1]);

fprintf(file1,"\nWritten to file\n");

fclose(file1);


return 0;
}   

首先,超出数组范围会导致 undefined behavior。当您遍历 argv 数组而不检查例如i < argc(除非您实际上在命令行上提供了超过 48 个参数)。

其次,为什么在超出argv范围时打印环境变量,这是因为在POSIX系统(如Linux或macOS)上有一个[= main 函数的第三个 参数,通常称为 environ。与 argv 类似,它是一个包含环境变量的字符串数组(以相同的方式声明,例如 char *environ[])。通过超出 argv 的范围,您将进入 environ 数组的内存。


在相关说明中,您使用 argv[2] 时没有检查参数是否确实存在,或者它不是您使用 getopt 解析的任何其他参数。不要那样做。

还要注意 getopt 函数 returns 和 int。这实际上对于检查 -1(不是 EOF!)非常重要。