Py_INCREF() incomprehension

Hegedüs Ervin airween at gmail.com
Tue Apr 26 07:01:13 EDT 2011


Hello,

thanks for the reply,

> >static PyObject*
> >mycrypt_encrypt(PyObject *self, PyObject *args)
> >{
> >     int cRes = 0;
> >     int OutLen = 0;
> >
> >     char *  url;
> >     char *  path;
> >
> >     if (!PyArg_ParseTuple(args, "ss",&url,&path)) {
> 
> Use the "s#" format instead to get the length as well.

oh, thanks, I'll check it out,
 
> >         return NULL;
> >     }
> >
> >     OutLen = strlen(url)*4;
> >     outdata=calloc(OutLen, sizeof(char));
> >
> >     if (!outdata) {
> >         handle_err(UER_NOMEM);
> 
> I assume this raises MemoryError?

yes,

another question should be: do I need to use
Py_INCREF()/Py_DECREF() at exception objects?

There are several error types, which has defined in 3rd-party
header file, based on these I've created my exceptions:

...
static PyObject *cibcrypt_error_badparm;
static PyObject *cibcrypt_error_nomem;
static PyObject *cibcrypt_error_badsize;
...

void handle_err(int errcode) {
    switch(errcode) {
...
        case -4:    PyErr_SetString(cibcrypt_error_badparm, "Bad parameter");
                    break;

        case -5:    PyErr_SetString(cibcrypt_error_nomem, "Not enough memory");
                    break;

        case -6:    PyErr_SetString(cibcrypt_error_badsize, "Invalid buffer size");
                    break;
...
}


PyMODINIT_FUNC
initcibcrypt(void)
{
    PyObject *o;
    o = Py_InitModule3("mycrypt", mycrypt_methods, mycrypt_doc);
...
    cibcrypt_error_badparm = PyErr_NewException("cibcrypt.error_badparm", NULL, NULL);
    cibcrypt_error_nomem = PyErr_NewException("cibcrypt.error_nomem", NULL, NULL);
    cibcrypt_error_badsize = PyErr_NewException("cibcrypt.error_badsize", NULL, NULL);
...

    PyModule_AddObject(o, "error", cibcrypt_error_badparm);
    PyModule_AddObject(o, "error", cibcrypt_error_nomem);
    PyModule_AddObject(o, "error", cibcrypt_error_badsize);
...
}

is that correct?

 
> >         return NULL;
> >     }
> >     cRes = ekiEncodeUrl (url, strlen(url)+1, outdata,&OutLen, 1, path);
> >
> >     if (cRes == 0) {
> >         return Py_BuildValue("s", outdata);
> 
> You are leaking the memory allocated for outdata here.

ok, and how can I handle that leak? When should I use the
Py_DECREF, or any other function (eg: free()?))?
 
> And, again, use the "s#" format.
> 
> 
> >     } else {
> >         handle_err(cRes);
> >         return NULL;
> >     }
> 
> I assume this raises an appropriate exception?

yes, see the handle_error() function.

> 
> >     return Py_None;
> 
> This is unreachable code.

yes, that's just an old typo, I think I purged these... thanks.

> >where ekiEncodeUrl is in a 3rd-party library.
> >I should call this function from Python like this:
> >
> >import mycrypt
> >
> >message = "PID=IEB0001&MSGT=10&TRID=000000012345678"
> >crypted = mycrypt(mymessage, "/path/to/key");
> >
> >Everything works fine, but sorry for the recurrent question: where
> >should I use the Py_INCREF()/Py_DECREF() in code above?
> 
> These two functions are not your problem here.

which two functions did you mean?
If you mean encrypt/decrypt (above), why did you wrote there is a
memleak?

> In any case, I recommend using Cython instead of plain C. It keeps
> you from getting distracted too much by reference counting and other
> CPython C-API details, so that you can think more about the
> functionality you want to implement.

ok, I'll try to see CPython, but - just for my passion :) - what
is the solution to handle the leak above?



Thanks again:


a.



More information about the Python-list mailing list