<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii">
<META NAME="Generator" CONTENT="MS Exchange Server version 5.5.2657.73">
<TITLE>Python Strings and PyMem_Malloc/Free</TITLE>
</HEAD>
<BODY>

<P><FONT SIZE=2>Hi,</FONT>
</P>

<P><FONT SIZE=2>I fear I may have been operating under a false assumption with regards to creating Python strings. This assumption goes like this:</FONT></P>

<P><FONT SIZE=2>1) Whatever memory you PyMem_Malloc you should always PyMem_Free.</FONT>
<BR><FONT SIZE=2>2) For strings you malloc and need to turn into python strings assign them to a python variable in Pyrex then PyMem_Free the pointer to the string before you return the python object.</FONT></P>

<P><FONT SIZE=2>3) This shouldn't present a problem because PyString_FromString copies the string to an internal representation (this is my assumption).</FONT></P>

<P><FONT SIZE=2>I believe the last statement may be completely erroneous :). Here is some code based upon this assumption:</FONT>
</P>

<P><FONT SIZE=2>cdef class Interface:</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; cdef TRK_HANDLE trkHandle</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; cdef TRK_ASSOC_HANDLE trkAssociationHandle</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; cdef TRK_RECORD_HANDLE trkRecordHandle</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; cdef TRK_NOTE_HANDLE trkNoteHandle</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; cdef TRK_ATTFILE_HANDLE trkAttFileHandle</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; cdef TRK_IMPORT_HANDLE trkImportHandle</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; cdef TRK_EXPORT_HANDLE trkExportHandle</FONT>
</P>

<P><FONT SIZE=2>&nbsp;&nbsp;&nbsp; .</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; .</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; .</FONT>
</P>

<P><FONT SIZE=2>&nbsp;&nbsp;&nbsp; def GetNote(self):</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cdef TRK_UINT bufferSize, remaining, max, titleSize, result</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cdef LPSTR buffer, title, temp_buffer</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = TrkGetNoteDataLength(self.trkNoteHandle, &amp;bufferSize)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if result != TRK_SUCCESS:</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise ExtensionExceptions.TrackerError, result</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer = &lt;LPSTR&gt;PyMem_Malloc(sizeof(char)*bufferSize)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if buffer == NULL:</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise Exception, &quot;Could not malloc %d bytes!!&quot; % bufferSize</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp_buffer = &lt;LPSTR&gt;PyMem_Malloc(sizeof(char)*bufferSize)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if temp_buffer == NULL:</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise Exception, &quot;Could not malloc %d bytes!!&quot; % bufferSize</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memset(buffer, 0x00, bufferSize)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memset(temp_buffer, 0x00, bufferSize)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if bufferSize &gt; 10000:</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max = 10000</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else:</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max = bufferSize</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; remaining = bufferSize</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pyNote = ''</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while remaining != 0:</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = TrkGetNoteData(self.trkNoteHandle, max, temp_buffer, &amp;remaining)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if result != TRK_SUCCESS and result != TRK_E_DATA_TRUNCATED:</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PyMem_Free(buffer)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PyMem_Free(temp_buffer)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise ExtensionExceptions.TrackerError, result</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buffer, temp_buffer)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memset(temp_buffer, 0x00, bufferSize)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; titleSize = 200</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; title = &lt;LPSTR&gt;PyMem_Malloc(sizeof(char)*titleSize)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if title == NULL:</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise Exception, &quot;Could not malloc %d bytes!!&quot; % titleSize</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memset(title, 0x00, titleSize)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = TrkGetNoteTitle(self.trkNoteHandle, titleSize, title)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if result != TRK_SUCCESS:</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PyMem_Free(buffer)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PyMem_Free(temp_buffer)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PyMem_Free(title)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise ExtensionExceptions.TrackerError, result</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pyTitle = title</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pyNote = buffer</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # it is this code that appears to be problematic</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PyMem_Free(buffer)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PyMem_Free(temp_buffer)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PyMem_Free(title)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (pyTitle,pyNote)</FONT>
</P>

<P><FONT SIZE=2>As the code stands calling this function _sometimes_ crashes the Python interpreter (usually the 3rd or 5th call) with an access violation (mem address 0x0000000 which would imply a null pointer reference). If I comment out the final three calls to PyMem_Free then the problem does not arise.</FONT></P>

<P><FONT SIZE=2>If my assumption is wrong does the same hold true for structures? I have similar malloc/free calls for structures which save data from them and then free the structure memory before returning.</FONT></P>

<P><FONT SIZE=2>Any information is appreciated,</FONT>
</P>

<P><FONT SIZE=2>Grant M.</FONT>
</P>

</BODY>
<!--[object_id=#infocomp.com#]--><P><FONT face=Arial color=#808080 size=1>Important notice: This message is intended for the individual(s) and entity(s) addressed. The information contained in this transmission and any attached, may be confidential and may also be the subject of legal privilege, public interest immunity or legal professional privilege. Any review, retransmission, dissemination or other use of, taking of any action in reliance upon this information by person or entities other than the recipient is prohibited and requires authorization from the sender. If you are not the addressee indicated in this message (or responsible for delivery of the message to such person) you may not copy or deliver this message to anyone. In such cases you should destroy this message and kindly notify the sender by reply email. </FONT></P>
<P><FONT face=Arial color=#808080 size=1>WARNING: Although Infocomp has taken reasonable precautions so that no viruses&nbsp;are present in this e-mail, the company cannot accept responsibility for any loss or damage arising from the use of e-mail attachments.</FONT></P></HTML>