The "environment" is an unordered set of key-value pairs. The keys are strings and so are the values. If you have a terminal open, you can see what your current environment looks like by typing env. It might look a little bit like this:
ORBIT_SOCKETDIR=/tmp/orbit-cmccabe HOSTNAME=highcastle IMSETTINGS_INTEGRATE_DESKTOP=yes TERM=xterm SHELL=/bin/bash HISTSIZE=1000 GTK_RC_FILES=/etc/gtk/gtkrc:/home/cmccabe/.gtkrc-1.2-gnome2 WINDOWID=44042990 QTDIR=/usr/lib64/qt-3.3 QTINC=/usr/lib64/qt-3.3/include IMSETTINGS_MODULE=none JAVA_OPTS=-Xcheck:jni:nonfatal USER=cmccabe CSCOPE_EDITOR=/usr/bin/vim ...Environment varibles are a simple and elegant way of passing around configuration information. It's easy to put a bunch of configuration variables into a script, and simply run that script before your application runs. You don't need to write a parser or ask your users to define a new configuration file syntax. Environment variables are accessible from any programming language, and available on any of the major platforms (Linux, Windows, MacOS.)
You can read an environment variable with getenv. You can remove environment variables with clearenv or unsetenv. You can set an environment variable with setenv or putenv.
The solution is simple: just hold a mutex while accessing or modifying the environment. However, this makes using environment variables a lot more cumbersome. It also makes it difficult to use environment variables in a shared library, or in a scripting language embedded in a larger application.
If you call free on a variable that was not originally allocated with malloc, heap corruption will result. On the other hand, if you don't free a variable that was malloced earlier, that is a memory leak. It's quite a dilemma, and POSIX is no help at all here.
There are actually three ways to set environment variables on Linux. You could use putenv, setenv, or modify the global variable environ. putenv is the simplest way. You give it a pointer to a string of the form KEY=VALUE, and it adds that pointer to the global environment. setenv tries to be more clever. It will use malloc to create a new KEY=VALUE string based on the KEY and VALUE that you pass to it.
Personally, I prefer to use putenv when adding environment variables. With putenv, you can avoid memory leaks by using statically allocated strings. The other method does not give you this choice. setenv does not exist on HPUX, Solaris, and some other UNIX platforms. However, putenv is mis-implemented as setenv on Mac OS X, FreeBSD, and some ancient Linux platforms.
Your best bet is probably to avoid modifying the environment at all, if possible. If that is not possible, try wrapping all accesses to the environment with a mutex , and modifying environ yourself, to make sure nobody is mallocing behind your back.
Stepping back a little bit, are these memory leaks and race conditions really such a big deal? Well, even small memory leaks can be annoying if they clutter up the output of tools like valgrind, a memory leak diagnosis tool. Also, once you allow incorrect code in your program, it tends to propagate itself, as new programmers look to the old code for examples of how to do things. Do yourself a favor and get it right the first time. As Captain Planet would no doubt say, cleaning up the environment is everyone's responsibility.
Russian Translation (Финалист сетенов)