<!DOCTYPE html PUBLIC
"-//W3C//DTD HTML 4.0 Transitional//EN">
<link rel=
"STYLESHEET" href=
"ext.css" type='text/css'
/>
<link rel=
"SHORTCUT ICON" href=
"../icons/pyfav.png" type=
"image/png" />
<link rel='start' href='../index.html' title='Python Documentation Index'
/>
<link rel=
"first" href=
"ext.html" title='Extending and Embedding the Python Interpreter'
/>
<link rel='contents' href='contents.html'
title=
"Contents" />
<link rel='last' href='about.html' title='About this document...'
/>
<link rel='help' href='about.html' title='About this document...'
/>
<link rel=
"next" href=
"nullPointers.html" />
<link rel=
"prev" href=
"ownershipRules.html" />
<link rel=
"parent" href=
"refcounts.html" />
<link rel=
"next" href=
"nullPointers.html" />
<meta name='aesop' content='information'
/>
<div id='top-navigation-panel' xml:id='top-navigation-panel'
>
<table align=
"center" width=
"100%" cellpadding=
"0" cellspacing=
"2">
<td class='online-navigation'
><a rel=
"prev" title=
"1.10.2 Ownership Rules"
href=
"ownershipRules.html"><img src='../icons/previous.png'
border='
0' height='
32' alt='Previous Page' width='
32'
/></A></td>
<td class='online-navigation'
><a rel=
"parent" title=
"1.10 Reference Counts"
href=
"refcounts.html"><img src='../icons/up.png'
border='
0' height='
32' alt='Up One Level' width='
32'
/></A></td>
<td class='online-navigation'
><a rel=
"next" title=
"1.10.4 NULL Pointers"
href=
"nullPointers.html"><img src='../icons/next.png'
border='
0' height='
32' alt='Next Page' width='
32'
/></A></td>
<td align=
"center" width=
"100%">Extending and Embedding the Python Interpreter
</td>
<td class='online-navigation'
><a rel=
"contents" title=
"Table of Contents"
href=
"contents.html"><img src='../icons/contents.png'
border='
0' height='
32' alt='Contents' width='
32'
/></A></td>
<td class='online-navigation'
><img src='../icons/blank.png'
border='
0' height='
32' alt='' width='
32'
/></td>
<td class='online-navigation'
><img src='../icons/blank.png'
border='
0' height='
32' alt='' width='
32'
/></td>
<div class='online-navigation'
>
<b class=
"navlabel">Previous:
</b>
<a class=
"sectref" rel=
"prev" href=
"ownershipRules.html">1.10.2 Ownership Rules
</A>
<b class=
"navlabel">Up:
</b>
<a class=
"sectref" rel=
"parent" href=
"refcounts.html">1.10 Reference Counts
</A>
<b class=
"navlabel">Next:
</b>
<a class=
"sectref" rel=
"next" href=
"nullPointers.html">1.10.4 NULL Pointers
</A>
<!--End of Navigation Panel-->
<H2><A NAME=
"SECTION0031030000000000000000"></A><A NAME=
"thinIce"></A>
There are a few situations where seemingly harmless use of a borrowed
reference can lead to problems. These all have to do with implicit
invocations of the interpreter, which can cause the owner of a
reference to dispose of it.
The first and most important case to know about is using
<tt class=
"cfunction">Py_DECREF()
</tt> on an unrelated object while borrowing a
reference to a list item. For instance:
<div class=
"verbatim"><pre>
PyObject *item = PyList_GetItem(list,
0);
PyList_SetItem(list,
1, PyInt_FromLong(
0L));
PyObject_Print(item, stdout,
0); /* BUG! */
This function first borrows a reference to
<code>list[
0]
</code>, then
replaces
<code>list[
1]
</code> with the value
<code>0</code>, and finally prints
the borrowed reference. Looks harmless, right? But it's not!
Let's follow the control flow into
<tt class=
"cfunction">PyList_SetItem()
</tt>. The list
owns references to all its items, so when item
1 is replaced, it has
to dispose of the original item
1. Now let's suppose the original
item
1 was an instance of a user-defined class, and let's further
suppose that the class defined a
<tt class=
"method">__del__()
</tt> method. If this
class instance has a reference count of
1, disposing of it will call
its
<tt class=
"method">__del__()
</tt> method.
Since it is written in Python, the
<tt class=
"method">__del__()
</tt> method can execute
arbitrary Python code. Could it perhaps do something to invalidate
the reference to
<code>item
</code> in
<tt class=
"cfunction">bug()
</tt>? You bet! Assuming
that the list passed into
<tt class=
"cfunction">bug()
</tt> is accessible to the
<tt class=
"method">__del__()
</tt> method, it could execute a statement to the effect of
"<tt class="samp
">del list[0]</tt>", and assuming this was the last reference to that
object, it would free the memory associated with it, thereby
invalidating
<code>item
</code>.
The solution, once you know the source of the problem, is easy:
temporarily increment the reference count. The correct version of the
<div class=
"verbatim"><pre>
PyObject *item = PyList_GetItem(list,
0);
PyList_SetItem(list,
1, PyInt_FromLong(
0L));
PyObject_Print(item, stdout,
0);
This is a true story. An older version of Python contained variants
of this bug and someone spent a considerable amount of time in a C
debugger to figure out why his
<tt class=
"method">__del__()
</tt> methods would fail...
The second case of problems with a borrowed reference is a variant
involving threads. Normally, multiple threads in the Python
interpreter can't get in each other's way, because there is a global
lock protecting Python's entire object space. However, it is possible
to temporarily release this lock using the macro
Py_BEGIN_ALLOW_THREADS, and to re-acquire it using
Py_END_ALLOW_THREADS. This is common around blocking
I/O calls, to let other threads use the processor while waiting for
the I/O to complete. Obviously, the following function has the same
problem as the previous one:
<div class=
"verbatim"><pre>
PyObject *item = PyList_GetItem(list,
0);
...some blocking I/O call...
PyObject_Print(item, stdout,
0); /* BUG! */
<div class='online-navigation'
>
<table align=
"center" width=
"100%" cellpadding=
"0" cellspacing=
"2">
<td class='online-navigation'
><a rel=
"prev" title=
"1.10.2 Ownership Rules"
href=
"ownershipRules.html"><img src='../icons/previous.png'
border='
0' height='
32' alt='Previous Page' width='
32'
/></A></td>
<td class='online-navigation'
><a rel=
"parent" title=
"1.10 Reference Counts"
href=
"refcounts.html"><img src='../icons/up.png'
border='
0' height='
32' alt='Up One Level' width='
32'
/></A></td>
<td class='online-navigation'
><a rel=
"next" title=
"1.10.4 NULL Pointers"
href=
"nullPointers.html"><img src='../icons/next.png'
border='
0' height='
32' alt='Next Page' width='
32'
/></A></td>
<td align=
"center" width=
"100%">Extending and Embedding the Python Interpreter
</td>
<td class='online-navigation'
><a rel=
"contents" title=
"Table of Contents"
href=
"contents.html"><img src='../icons/contents.png'
border='
0' height='
32' alt='Contents' width='
32'
/></A></td>
<td class='online-navigation'
><img src='../icons/blank.png'
border='
0' height='
32' alt='' width='
32'
/></td>
<td class='online-navigation'
><img src='../icons/blank.png'
border='
0' height='
32' alt='' width='
32'
/></td>
<div class='online-navigation'
>
<b class=
"navlabel">Previous:
</b>
<a class=
"sectref" rel=
"prev" href=
"ownershipRules.html">1.10.2 Ownership Rules
</A>
<b class=
"navlabel">Up:
</b>
<a class=
"sectref" rel=
"parent" href=
"refcounts.html">1.10 Reference Counts
</A>
<b class=
"navlabel">Next:
</b>
<a class=
"sectref" rel=
"next" href=
"nullPointers.html">1.10.4 NULL Pointers
</A>
<span class=
"release-info">Release
2.4.2, documentation updated on
28 September
2005.
</span>
<!--End of Navigation Panel-->
See
<i><a href=
"about.html">About this document...
</a></i> for information on suggesting changes.