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

int main(int argc, char *argv[], char *envp[])
{
    int i = 0;
    while (envp[i] != NULL)
    {
        if (strstr(envp[i], "SHLVL") != NULL)
            printf("%s\n", envp[i]);
        i++;
    }
  
    setenv("SHLVL", "stackoverflow", 2);
    i = 0;
    while (envp[i] != NULL)
    {
        if (strstr(envp[i], "SHLVL") != NULL)
            printf("%s\n", envp[i]);
        i++;
    }
    return 0;
}

在这个代码中,SHLVL是一个现有的环境变量.当我try 使用setenv更改该变量的值时,它会给出预期的输出.

SHLVL=1
SHLVL=stackoverflow

在另一种情况下: 不存在环境变量的相同代码

int main(int argc, char *argv[], char *envp[])
{
    int i = 0;
    while (envp[i] != NULL)
    {
        if (strstr(envp[i], "SHLVL") != NULL)
            printf("%s\n", envp[i]);
        i++;
    }

    setenv("arr", "33", 2); // non-exist environmental variable 
    setenv("SHLVL", "stackoverflow", 2);
    i = 0;
    while (envp[i] != NULL)
    {
        if (strstr(envp[i], "SHLVL") != NULL)
            printf("%s\n", envp[i]);
        i++;
    }
    return 0;
}

这里的arr是一个不存在的环境变量.此代码给出的输出为

SHLVL=1
SHLVL=1

我的问题是,不存在的环境变量如何改变这里的输出?这里我用的是GCC编译器.

推荐答案

main中的envp参数指向具有环境变量定义的原始array.使用setenv()设置EN环境变量时:

  • 如果变量已经存在,则不会重新分配数组,只会更改变量的条目,因此枚举由envp指向的数组会产生预期的输出.

  • 如果变量不存在,则具有所有定义的数组需要扩展,并且可能需要为此重新分配或移动,因此仍然指向原始数组的envp指针没有新数组中存在的当前定义字符串,getenv()使用该字符串来定位当前定义.在这种情况下,使用envp枚举值将找不到新的变量定义,如果一个现有变量后来被更改,如您的示例中所示,只有新数组被修改,envp指向的原始数组不会被修改,因此它仍然具有原始定义.这解释了您观察到的情况,但不能保证这种行为,因为根据实现的不同,原始数组在末尾可能有足够的空间用于新定义,因此不需要 for each 新变量重新分配.

这种行为非常棘手,对定义字符串的内存管理有深远的影响. 将envp传递到main不是标准的,并且仅在unix系统上可用,但即使在这些系统上,枚举环境定义的优选方式也是使用由setenv()putenv()更新的全局变量environ:

extern char **environ;

C++相关问答推荐

在x86汇编中,为什么当分子来自RDRAND时DIV会引发异常?

如何将FileFilter添加到FileDialog GTK 4

有效地计算由一组点构成的等边三角形和等腰三角形的数量

当多个线程在C中写入相同的文件描述符时,如何防止争用情况?

为什么GCC可以调用未定义的函数?

如何将字符串argv[]赋给C中的整型数组?

从纯C中访问通用项对话框

在列表中插入Int指针(C)

向上强制转换C中的数值类型总是可逆的吗?

进程在写入管道时挂起

错误:包含文件时类型名称未知

Kdb:仅升级指定的列

FRIDA-服务器成为端口扫描的目标?

为什么指针运算会产生错误的结果?

如何将另一个数组添加到集合中,特别是字符串?

CS50判断灯泡运动的问题,判断时多出一个灯泡,但不在终端上

pthread_create的用法

C";中的ANN运行时判断失败#2-变量outputLayer;周围的堆栈已损坏.运行后出错

C23标准是否向后兼容?

gdb - 你能找到持有内部 glibc 锁的线程吗?