Re: set-environment-variable Lassi Kortela 07 Dec 2019 20:12 UTC
> 1) They inherently and unavoidably leak memory, even though setenv() > copies its arguments before putting them in the environment. The > problem is created by the existence of putenv(), which is required by > both ISO C and Posix. Putenv() deliberately does *not* copy its > argument; rather, the argument becomes part of the environment data > structure. This means putenv() by itself is deterministic: if you > unsetenv() the variable, or if you are about to putenv() it again, the > memory used by the previous putenv can be free()d, or can even be a > stack variable if you are careful. > > But having both putenv() and setenv() means that setenv() and unsetenv() > *cannot free* the entry they are about to remove, because it may have > been inserted by putenv. So if you are using setenv() freely, you have > a permanent (though usually small) memory leak. I've never thought of that. OpenBSD libc (which is known for its attention to correctness) never frees any strings that are part of the environment. None of setenv(), putenv() and unsetenv() call free() on any string they remove from the environ array. environ itself it reallocarray()'d as needed. <https://github.com/openbsd/src/blob/master/lib/libc/stdlib/setenv.c> Not sure how much the memory leak matters. If an implementation wanted to go to a ton of effort, it could keep a list of pointers to "putenv() strings managed by Scheme" and the delete-environment-variable! could check whether it's one of those. > 2) The only reasons to modify the environment rather than changing a > variable initialized from the environment are these: > > 2a) to affect the behavior of some other part of the process, typically > some library (as TZ affects the time zone library). The trouble here is > that most such libraries do *not* expect these variables to change and > don't check whether they should mutate their internal view, so changing > the environment is likely to be ineffectual. (Fortunately, the Olson > time zone library provides a way to change the timezone directly without > changing the environment.) > > 2b) to pass a modified environment to a subprocess. But we can already > get the whole environment as an alist, and the ProcessesCowan pre-SRFI > accepts an alist and synthesizes a replacement environment from it. > Leaks don't matter here because memory will be discarded by the execve() > call, Maybe. setenv() tends to be a "set and forget" thing done at the start of the program. It also potentially causes problems in multi-threaded implementations. The text I wrote for the SRFI has some language to warn about that but it's not ideal to lock the environment array separately for each read and write operation.