Bug report: memory leak in python 1.5.2

Michael P. Reilly arcege at shore.net
Wed May 26 16:23:07 EDT 1999


Fred L. Drake <fdrake at cnri.reston.va.us> wrote:

: M.-A. Lemburg writes:
:  > Don't why the free(new); is missing though... maybe some putenv()
:  > implementation expect a malloced string (the putenv implementation
:  > in posixmodule.c for NeXT does) while other make a copy first.

:   At least on Solaris, the malloc()'ed memory must survive until the
: same key is re-used.
:   I think using a Python string for the malloc()'ed memory is
: acceptable (it's just a buffer, after all).  I took a stab at using a
: dictionary to "cache" the last string passed to putenv() for each key; 
: when using the same key again, the old value is removed from the
: dictionary and deleted.  Greg's code doesn't appear to leak with my
: patch, at any rate (running for over 7 minutes on a 200Mhz
: UltraSPARC).
:   I've appended the patch below for others to try out and verify.  If
: others get positive results and can't think of reasons not to accept
: this, perhaps I can knock Guido over the head with it when he gets
: back to town.  ;-)

There is also the situation where some UNIX systems put the environment
initially in the u area, and it is difficult to programmatically determine
where different runtime segments are (where is the heap vs. where is the
u area).

Fred, your solution should work because it takes the problem case: what
to do with the string initially, but I think it might be better to copy
the values at module initialization time.  I've included an addition to
Fred's patch to be called instead of the PyDict_New() function (in the
module init function).

Also, how should we deal with this in terms of C applications who might
change the environment?  (Embedders beware!)

>From a programming standpoint, I don't think that it should be "proper"
to be changing the environment all that much.  It's purpose is to
propragate values to child processes, not to store runtime values.

  -Arcege

Example environment initialization schema (based on Fred Drake's patch).

PyObject *
system_environ_initialize(environ)
  char **environ;
  { int i;
    char **p;
    PyObject *putenv_garbage;
    PyObject *key, *env;

    if ((posix_putenv_garbage = PyDict_New()) == NULL)
      return NULL;
    /* populate the dictionary with the values from the environment */
    for (p = environ; *p; p++)
      /* get the name of the environment variable */
      for (i = 0; (*p)[i] && (*p)[i] != '='; i++) ;
      key = PyString_FromStringAndSize(*p, i);
      env = PyString_FromString(*p);
      PyDict_SetItem(posix_putenv_garbage, key, env);
      Py_DECREF(key);
      Py_DECREF(env);
    }
    i = 0;
    /* rewrite the entire environment with Python strings */
    /* we rewrite the entire environment after reading it, not while
       reading the address locations */
    while (PyDict_Next(posix_putenv_garbage, &i, &key, &env))
      putenv(PyString_AS_STRING(env));
    return posix_putenv_garbage;
  }





More information about the Python-list mailing list