Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

For example, when compiled with GCC 3.4.6 and run on a 32-bit Intel GNU/Linux machine, the following code,

Code Block
#include <stdio.h>
#include <stdlib.h>
 
extern char **environ;

/* ... */

int main(int argc, const char *argv[], const char *envp[]) {
   printf("environ:  %p\n", environ);
   printf("envp:     %p\n", envp);
   setenv("MY_NEW_VAR", "new_value", 1);
   puts("--Added MY_NEW_VAR--");
   printf("environ:  %p\n", environ);
   printf("envp:     %p\n", envp);
  return 0;
}

yields

Code Block
% ./envp-environ
environ: 0xbf8656ec
envp:    0xbf8656ec
--Added MY_NEW_VAR--
environ: 0x804a008
envp:    0xbf8656ec

...

Code Block
bgColor#ffcccc
langc
#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, const char *argv[], const char *envp[]) {
   size_t i;
   if (setenv("MY_NEW_VAR", "new_value", 1) != 0) {
     /* Handle error */
   }
   if (envp != NULL) {
      for (size_t i = 0; envp[i] != NULL; i++i) {
         if (puts(envp[i]) == EOF) {
           /* Handle error */
         }
      }
   }
   return 0;
}

Because envp may no longer point to the current environment, this program has undefined behavior.

...

Code Block
bgColor#ccccff
langc
#include <stdio.h>
#include <stdlib.h>
 
extern char **environ;

/* ... */

int main(int argc, const char *argv[]) {
   size_t i;
   if (setenv("MY_NEW_VAR", "new_value", 1) != 0) {
     /* Handle error */
   }
   if (environ != NULL) {
      for (size_t i = 0; environ[i] != NULL; i++i) {
         if (puts(environ[i]) == EOF) {
           /* Handle error */
         }

      }
   }
   return 0;
}

Noncompliant Code Example (Windows)

...

Code Block
bgColor#ffcccc
langc
#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, const char *argv[], const char *envp[]) {
   size_t i;
   if (_putenv_s("MY_NEW_VAR", "new_value") != 0) {
     /* Handle error */
   }
   if (envp != NULL) {
      for (size_t i = 0; envp[i] != NULL; i++i) {
         if (puts(envp[i]) == EOF) {
           /* Handle error */
         }
      }
   }
   return 0;
}

Because envp no longer points to the current environment, this program fails to print the value of MY_NEW_VAR.

...

Code Block
bgColor#ccccff
langc
#include <stdio.h>
#include <stdlib.h>
 
_CRTIMP extern char **_environ;

/* ... */

int main(int argc, const char *argv[]) {
   size_t i;
   if (_putenv_s("MY_NEW_VAR", "new_value") != 0) {
     /* Handle error */
   }
   if (_environ != NULL) {
      for (i = 0; _environ[i] != NULL; i++i) {
         if (puts(_environ[i]) == EOF) {
           /* Handle error */
         }
      }
   }
   return 0;
}

Compliant Solution

...

Code Block
bgColor#ccccff
langc
#if  defined (_POSIX_) || defined (__USE_POSIX)
  extern char **environ;
  #define envp environ
#else#elif defined(_WIN32)
  _CRTIMP extern char **_environ;
  #define envp _environ
#endif

int main(int argc, char *argv[]) {
  /* ... */
}

...

Bibliography

...