#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;
}
In this code SHLVL is an existing environmental variable. When I try to change the value of that variable using setenv it gives expected output.
SHLVL=1
SHLVL=stackoverflow
In another case: The same code with non-existent environmental variable
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;
}
Here the arr is an non-exist environmental variable. This code give output as
SHLVL=1
SHLVL=1
My question is how the non-existing environmental variable change the output here? Here I am using gcc compiler.
The
envpargument inmainpoints to the original array with environment variable definitions. When you set en environment variable usingsetenv():If the variable already exists, the array is not reallocated, only the entry for the variable is changed, hence enumerating the array pointed to by
envpgives the expected output.If the variable does not exist, the array with all definitions needs to be extended and may need to be reallocated or moved for this purpose, hence the
envppointer that still points to the original array does not have the current definition strings that are present in the new array, the one used bygetenv()to locate the current definitions. In this case, enumerating the values usingenvpwill not find the new variable definition and if an existing variable is changed afterwards as in your example, only the new array is modified, the original array pointed to byenvpis not modified so it still has the original definition. This explains what you observe, but this behavior is not guaranteed as, depending on the implementation, the original array might have enough space at the end for the new definition and thus would not need to be reallocated for each new variable.This behavior is very tricky and has far reaching consequences for the memory management of definition strings. Passing the
envptomainis not standard and only available on unix systems, but even on these systems, a preferred way of enumerating the environment definitions is to use the global variableenvironthat is updated bysetenv()andputenv():