"Memory could not be Read/Written" crashes with C extension DLL... HELP PLEASE!

Chris Liechti cliechti at gmx.net
Sat Apr 6 13:18:06 EST 2002


kevin at cazabon.com (Kevin Cazabon) wrote in 
news:5a4226f0.0204052223.75aa0318 at posting.google.com:
> I've gotten past many hurdles so far, but I can't seem to figure out
> what's causing my problems.  The DLL I've built works just fine...
> unless you call pyHasp (see below) multiple times (random.. sometimes
> it works fine for 40 calls, sometimes it works for 300 calls, then
> crashes).
> 
...
> ///////////////////////////////////////////////////////////////
> static PyObject *
> pyHasp(PyObject *self, PyObject *args)
> {
>   // declarations
>   PyObject *pReturn = NULL;
> 
>   PyObject *pLong1 = NULL;
>   PyObject *pLong2 = NULL;
>   PyObject *pLong3 = NULL;
>   PyObject *inBuffer = NULL;
>   int inBufferSize = 0;
> 
>   char *pInBufferAsReadBuffer = NULL;
>   char *pInBufferAsWriteBuffer = NULL;
> 
>   ULONG Service = 0;
>   ULONG SeedCode = 0;
>   ULONG LptNum = 0;
>   ULONG Pass1 = 0;
>   ULONG Pass2 = 0;
> 
>   ULONG p1 = 0;
>   ULONG pp1 = 0;
>   ULONG p2 = 0;
>   ULONG p3 = 0;
>   ULONG pp3 = 0;
> 
>   char *EncodeDecodeBuffer = NULL;
>   ULONG pUL_EncodeDecodeBuffer = 0;
> 
>   // parse the PyObject arguments, assign to variables accordingly
>   // inBuffer is a Python 'B' array, which supports the buffer
> interface
>   if (!PyArg_ParseTuple(args, "llllllllOl", &Service, &SeedCode,
> &LptNum, &Pass1, &Pass2, &p1, &p2, &p3, &inBuffer, &inBufferSize)) {
>     return Py_BuildValue("llls", -9999, -9999, -9999, "Could not parse
> the Python Tuple!");

PyArg_ParseTuple already set up an exception. it usual to "return NULL;" 
here.


>   }
> 
>   // Check the size of the inBuffer for validity
>   if (inBufferSize > 1000) {
>     return Py_BuildValue("llls", -9998, -9998, -9998, "Encode / Decode
> buffer must be less than 1000 characters.");
>   }
> 
>   if (inBufferSize < 8) {
>     return Py_BuildValue("llls", -9997, -9997, -9997, "Encode / Decode
> buffer must be 8 characters or more in length.");
>   }
> 
>   // allocate the memory for the EncodeDecodeBuffer
>   EncodeDecodeBuffer = malloc(inBufferSize);
>   if (!EncodeDecodeBuffer) {
>     return Py_BuildValue("llls", -9994, -9994, -9994, "Could not
> allocate memory for the EncodeDecodeBuffer!");
>   }
>   memset (EncodeDecodeBuffer, 0, inBufferSize);
> 
>   // Obtain a pointer to the Python Buffer Interface for inBuffer
> (readable)
>   if (PyObject_CheckReadBuffer(inBuffer)) {
>     if ((Service != 1) && (Service != 5)) {
>       if (PyObject_AsReadBuffer(inBuffer, &pInBufferAsReadBuffer,
> &inBufferSize) == -1) { // PyObject_AsReadBuffer is fucked up in its
> return values... -1 is error, 0 is success
>         return Py_BuildValue("llls", -9995, -9995, -9995, "Could not
> access the passed string as a Python buffer!");

don't return here - you have a memory leak...
maloc is above and free below...

there follow some "return" with the same problem below

>       }
>     }
>   } 
>   else {
>       return Py_BuildValue("llls", -9995, -9995, -9995, "inBuffer does
> not support Buffer Interface!");
>   } 
> 
>   // the Python values should NOT be modified in place, make copies to
> pass to hasp function
>   pp1 = p1;
>   pp3 = p3;
> 
>   // copy the inBuffer to the EncodeDecodeBuffer, use memcpy so that
> nulls don't cause problems
>   if  ((Service != 1) && (Service != 5)) {
>     memcpy(EncodeDecodeBuffer, pInBufferAsReadBuffer, (unsigned
> int)inBufferSize);
>   }
> 
>   // get a ULONG pointer to EncodeDecodeBuffer
>   pUL_EncodeDecodeBuffer = (ULONG) EncodeDecodeBuffer;

you say "ULONG pointer" in the comment so i would expect that the cast is
"(ULONG *)". ok i see that pUL_EncodeDecodeBuffer
is declared as ULONG and not as pointer.

you're sure that the pointer is needed in that form?
usualy all pointers have the same byte-size e.g. 4 bytes on current PCs.
and when you speak of a ULONG pointer usualy a pointer to a long is meant, 
thus "ULONG *"

>   // send the data to the hasp driver for encoding/decoding/whatever
>   // this function modifies pp1, inBufferSize, pp3, EncodeDecodeBuffer
> (through the pUL_ pointer) in place
>   CallHasp(Service, SeedCode, LptNum, Pass1, Pass2, &pp1,
> &inBufferSize, &pp3, &pUL_EncodeDecodeBuffer);
> 
>   // copy the EncodeDecodeBuffer back to the inBuffer, through a
> pointer to the Python Buffer interface (writable)
>   if  ((Service != 1) && (Service != 5)) {
>     if (PyObject_AsWriteBuffer(inBuffer, &pInBufferAsWriteBuffer,
> &inBufferSize) == -1) {
>       return Py_BuildValue("llls", -9994, -9994, -9994,
> "PyObject_AsWriteBuffer Failed!");
>     }
>     memcpy(pInBufferAsWriteBuffer, EncodeDecodeBuffer, (unsigned
> int)inBufferSize);
>   }
> 
>   free(EncodeDecodeBuffer);
> 
> 
>   // build pp1, inBufferSize, pp3 into PyObjects for returning
>   pLong1 = PyLong_FromLong(pp1);
>   pLong2 = PyLong_FromLong(inBufferSize);
>   pLong3 = PyLong_FromLong(pp3);
> 
>   // build pLong1, pLong2, pLong3, pString into a tuple to return
> 
>   pReturn = PyTuple_New(4);
>   PyTuple_SetItem(pReturn, 0, pLong1); 
>   PyTuple_SetItem(pReturn, 1, pLong2);
>   PyTuple_SetItem(pReturn, 2, pLong3);
>   PyTuple_SetItem(pReturn, 3, inBuffer);

you could use Py_BuildValue here as well.

>   return pReturn;
> }
> 

why are you not using exceptions for the error handling? i think it would 
be much cleaner for the usage of this function.

-- 
Chris <cliechti at gmx.net>




More information about the Python-list mailing list