[Pyrex] Total newbie needs code review

Greg Ewing greg.ewing at canterbury.ac.nz
Mon Sep 12 07:22:32 CEST 2005


Grant McDonald wrote:

> What pyrex means by "Obtaining char * from temporary Python value" is 
> that you haven't created a char pointer variable to hold the string 
> value.

Er, not exactly. By "temporary Python value" it means
one of its internally generated local variables holding
an object reference. It's meant to catch things like

   cdef char *p
   p = s1 + s2

where s1 and s2 are Python strings. This generates
something like

   char *p;
   PyObject *__pyx_1;
   __pyx_1 = PyObject_Add(s1, s2);
   p = PyString_AsString(__pyx_1);
   Py_DECREF(__pyx_1);

The "temporary Python value" here is __pyx_1. This
piece of code can't possibly work correctly, because
the result of PyObject_Add in this case is a brand
new string object with no other references to it,
so it's going to go away as soon as the Py_DECREF
is executed, leaving p dangling.

It seemed to me it would be rather easy to fall
into this trap unawares, so I built in a heuristic
which essentially makes it an error to write something
which causes PyString_AsString to be applied to one
of these internal temporary variables. Being a
heuristic, sometimes it gets it wrong, rejecting
something that's actually okay, or accepting
something that's not okay.

In your case, it sounds like it's a false alarm,
although I'd have to see the exact piece of code
producing it to be sure.

 > The
> way to remove this warning from your code is to be explicit in your 
> conversions:

That's not quite correct. The way to remove it is to
make sure that the Python string reference you're starting
with (NOT the char *) is held in an explicitly-named
variable (local, global or parameter).

> doStuff(pyStuff)        # implicit
> 
> cStuff = pyStuff
> doStuff(cStuff)         # explicit

Both of those actually compile okay. An example of
something that *does* (currently) produce the error
is

   doStuff(foo.stuff)

and it can be removed by rewriting it as

   pyStuff = foo.stuff
   doStuff(pyStuff)

What grant wrote about mallocing a copy of the string
if you need to modify it is correct. I'd just add that
you should also malloc a copy if there is any chance
that the original Python string could get garbage
collected before you're finished with the C string.

-- 
Greg Ewing, Computer Science Dept, +--------------------------------------+
University of Canterbury,	   | A citizen of NewZealandCorp, a	  |
Christchurch, New Zealand	   | wholly-owned subsidiary of USA Inc.  |
greg.ewing at canterbury.ac.nz	   +--------------------------------------+



More information about the Pyrex mailing list