"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