I have a function that is copying the contents of the envp
array that contains the global variables. The function is successful in copying the contents, however, when it returns, it seems like the array pointer is pointing somewhere else altogether.
#include <stdio.h>
#include <string.h>
// allow up to 64 environment variables
#define MAXENV 64
// local envp copy
char *envp_copy[MAXENV];
// current size of envp_copy
int envp_size = 0;
void copy_envp(char *envp[])
{
for (long i = 0; i <= MAXENV; i++)
{
if (envp[i] == NULL)
{
envp_copy[i] = NULL;
break;
}
envp_copy[i] = strdup(envp[i]);
envp_size++;
}
for (int i = 0; i < envp_size; i++)
{
printf("%s\n", envp_copy[i]);
}
}
int main(int argc, char *argv[], char *envp[], char *envp_copy[])
{
copy_envp(envp);
for (int i = 0; i < envp_size; i++)
{
printf("%s\n", envp_copy[i]);
}
}
I know that if I change the copy_envp
function to take the array as variable
void copy_envp(char *envp[], char *envp_copy[]);
Then everything works as expected. But I am struggling to understand why the array has to be passed in as a parameter, even though it was declared globally.
The C standard defines main()
as taken either 0 or 2 arguments, or an "implementation-defined" manner and I only know of a 3rd argument with the char *environment[]
and not a of a 4th argument which in your program shadows the global variable.
Here is an implementation that avoids the global variable and addresses the memory leak (of the strings being strdup()
). It also addresses the out of bound access; i = 0; i <= MAXENV
is MAXENV + 1 loop iterations.
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXENV 64
char **copy_envp(const char *env[]) {
char **copy = malloc(sizeof *copy * (MAXENV+1));
if(!copy) return NULL;
int i = 0;
for(; i < MAXENV && env[i]; i++)
copy[i] = strdup(env[i]);
copy[i] = NULL;
// optionally shrink the copy to size
char **tmp = realloc(copy, sizeof *copy * (i+1));
return tmp ? tmp : copy;
}
int main(int argc, char *argv[], char *envp[]) {
char **envp_copy = copy_envp((const char **) envp);
if(!envp_copy) {
printf("copy_envp empty or failed\n");
return 1;
}
for (int i = 0; envp_copy[i]; i++) {
printf("%s\n", envp_copy[i]);
free(envp_copy[i]);
}
free(envp_copy);
}