Reference Count Confusion

Jeff Smith smithj at kryos.colorado.edu
Tue Jun 25 16:41:01 EDT 2002


I'm a little puzzled about reference counts from Python objects created
in a C extension. In the following example, I return a Numerical Python
array from a C function (function 'add' ). Just before the return,
I printed the reference count, and is was 1, as expected. When I passed
the returned array into another C function (function 'clean'), it's
reference count was 3. This wasn't what I expected, and probably
explains why when I incorporate C functions into my Python programs
I chew up gobs of memory. I'm presumably doing something wrong. Am
I supposed to decrement the reference count somewhere?

Python code:

import Numeric
import foo

a = Numeric.zeros(1000000).astype('f')
b = Numeric.ones(1000000).astype('f')
for i in range(10):
    d = foo.add(a, b)
    foo.clean(d)

C code (module 'foo'):

static PyObject *add(PyObject *self, PyObject *args)
{

  PyArrayObject *a, *b, *c;
  float *cb, *cc, *ca;
  int i;
  long buffer_size;

  if (!PyArg_ParseTuple(args, "OO", &a, &b))
    {
      return NULL;
    }

  buffer_size = a->dimensions[0];

  ca = (float *)a->data;
  cb = (float *)b->data;
  cc = (float *)malloc(buffer_size*sizeof(float));
  for (i = 0; i < buffer_size; i++)
    {
      cc[i] = ca[i] + cb[i];
    }

  c = (PyArrayObject *)PyArray_FromDims(1, (int *)&buffer_size, PyArray_FLOAT);
  memcpy(c->data, cc, buffer_size*sizeof(float));
  free(cc);

  printf("add: %d\n", c->ob_refcnt);
  return Py_BuildValue("O", c);
}

static PyObject *clean(PyObject *self, PyObject *args)
{
  PyArrayObject *c;

  PyArg_ParseTuple(args, "O", &c);

  printf("clean: %d\n", c->ob_refcnt);
  if (c->data != NULL) free(c->data);
  if (c->dimensions != NULL) free(c->dimensions);
  if (c->strides == NULL) free(c->strides);
  Py_DECREF(c);
  printf("clean: %d\n", c->ob_refcnt);

  return Py_BuildValue("");
}

--








More information about the Python-list mailing list