PyObject_CallObject code dump after calling 4 times

G

grbgooglefan

I have a following C++ code which uses PyObject_CallObject to evaluate
expressions dynamically. This code sets the input parameters for the
function also dynamically. After calling this function 4 times (with
these shown values), PyObject_CallObject causes application to crash
in frame_dealloc.
1) Can some one please help me understand why is this crash happening
in frame_dealloc & how to solve it?
2) Is there anything wrong I am doing about incrementing or
decrementing the reference counts of the object passed to
PyObject_CallObject?
3) Is it because of the big value (2299265.500000) I am trying to
convert from double to float using PyFloat_FromDouble?

//========================= code reduced for readability
===============
switch(ndtyp){
case(INT_T):
{
printf("PyInt_FromLong val %d, var %s
\n",inputVar.nionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
val = PyInt_FromLong(inputVar.nionum);
break;
}
case(LONG_T):
{
printf("PyLong_FromLong val %ld, var %s
\n",inputVar.lionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
val = PyLong_FromLong(inputVar.lionum);
break;
}
case(FLOAT_T):
{
printf("PyFloat_FromDouble val %f, var %s
\n",inputVar.fionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
val = PyFloat_FromDouble(inputVar.fionum);
break;
}
case(DOUBLE_T):
{
printf("PyFloat_FromDouble val %f, var %s
\n",inputVar.dionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
val = PyFloat_FromDouble(inputVar.dionum);
break;
}
case(STRING_T):
{
printf("PyString_FromString val %s, var %s
\n",inputVar.ioString,pEvalFunc->pExprVarsArray[nCtr].szVarName);
val = PyString_FromString(inputVar.ioString);
break;
}
default:
printf("Unknown data type [%d] for %s\n",ndtyp,pEvalFunc-
pExprVarsArray[nCtr].szVarName);
}
if(!val){
ret = -1;
printf("Failed to convert %d %s to PyObject\n",ndtyp,pEvalFunc-
pExprVarsArray[nCtr].szVarName); fflush(stdout);
Py_XDECREF(pTuple);
break;
}
PyTuple_SetItem(pTuple, nCtr, val);
Py_XDECREF(val);
}
// all variables are set, call Python function
Py_XINCREF(pTuple);
PyObject *pResult = PyObject_CallObject(pEvalFunc-
pPyEvalFunction,pTuple);
Py_XDECREF(pTuple);

if(PyErr_Occurred()){
PyErr_Print();
} else {
char* plevel = NULL;
if(NULL != (plevel = PyString_AsString(pResult))){
ret = 0;
sprintf(szEvalResult,"%s",plevel);
}
}
Py_XDECREF(pResult);
================================================
Following crash (back trace) appears when I run this in GDB. The
expression that was getting evaluated at this time is:
def DangerousQuantity(size,maxvol,adv):
if((size<1000 and (maxvol<10000) and (size<0.001*adv))):
return "Dangerous"
else:
return "FAIL"

//--------------- Crash dump information & values of variables passed
to this expression
Categorizing the order
pyParserEvaluator evaluating category function DangerousTactic
PyString_FromString val R, var aestactic
PyLong_FromLong val 1139, var endtime
PyLong_FromLong val 599, var starttime
PyLong_FromLong val 23, var Aggr
PyObject_CallObject done, do Py_XDECREF-pTuple
Final result FAIL
doing Py_XDECREF(pResult
pyParserEvaluator evaluating category function MediumTactic
PyString_FromString val R, var aestactic
PyLong_FromLong val 1139, var endtime
PyLong_FromLong val 599, var starttime
PyLong_FromLong val 23, var Aggr
PyObject_CallObject done, do Py_XDECREF-pTuple
Final result FAIL
doing Py_XDECREF(pResult
pyParserEvaluator evaluating category function SafeTactic
PyString_FromString val R, var aestactic
PyLong_FromLong val 1139, var endtime
PyLong_FromLong val 599, var starttime
PyLong_FromLong val 23, var Aggr
PyObject_CallObject done, do Py_XDECREF-pTuple
Final result FAIL
doing Py_XDECREF(pResult
pyParserEvaluator evaluating category function DangerousQuantity
PyLong_FromLong val 1, var size
PyLong_FromLong val 0, var maxvol
PyFloat_FromDouble val 2299265.500000, var adv

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 82336688 (LWP 27652)]
0xc0000000 in ?? ()
(gdb) where
#0 0xc0000000 in ?? ()
#1 0x0285e59e in frame_dealloc (f=0xf5a2f68c) at Objects/
frameobject.c:106
#2 0x0281a4b1 in PyEval_EvalCodeEx (co=0xf5a69990, globals=0x2884120,
locals=0x0, args=0x288bca0, argcount=3, kws=0x0, kwcount=0,
defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:2609
#3 0x0285f551 in function_call (func=0xf5a694c4, arg=0xf5a47c3c,
kw=0x0) at Objects/funcobject.c:476
#4 0x027e1e04 in PyObject_Call (func=0xf5a2003c, arg=0xf5a47c3c,
kw=0x0) at Objects/abstract.c:1688
#5 0x0281b3eb in PyEval_CallObjectWithKeywords (func=0xf5a694c4,
arg=0xf5a47c3c, kw=0x0) at Python/ceval.c:3058
#6 0x027e1de3 in PyObject_CallObject (o=0xf5a694c4, a=0xf5a47c3c) at
Objects/abstract.c:1679
#7 0x027dd6fd in pyParserEvaluator::EvaluateCategory
(this=0xf5a08df0, nCatLevelId=1, pOrdData=0x4e84f40,
szEvalResult=0x4e84b70 "Dangerous") at pyEvaluator.cpp:342
#8 0x0070da71 in ParseEvalDriver::categorizeOrder (this=0xf5a0cf20,
pcatRuleCache=0xfeff4e20, pOrdData=0x4e84f40,
szLevelResult=0x9876180) at IEvaluatorInterface.cpp:102
#9 0x0807e812 in HandleCheck (szTopic=0x96d0439 "CE/REQ_3_EX/NEW",
szReplyTopic=0x96d0639 "CE/RES_3_EX/njl36a-7003_401",
pBuff=0x9875688 "4056029121", nBuffLen=195, pUsr=0xfeff4e18) at
cerule.cpp:4859
#10 0x0032130d in CMiTssSub::OnRecvMsg (this=0xf5aaf0b0,
pszTopic=0x96d0439 "CE/REQ_3_EX/NEW",
pszReplyTopic=0x96d0639 "CE/RES_3_EX/njl36a-7003_401",
pmsg=0x98754e8) at src/mitss.cpp:1810
#11 0x0031dc01 in CMiTss::OnRecvMsg (pszTopic=0x96d0438 "/CE/REQ_3_EX/
NEW",
pszReplyTopic=0x96d0638 "/CE/RES_3_EX/njl36a-7003_401",
pszMsg=0x98755e8 "èT\207\tèT\207\t", nMsgLen=4, pUsr=0xf5aaf0b0)
at src/mitss.cpp:466
#12 0x0032296c in CMiHelper::_worker (arg=0x96cfc44) at mihelper.cpp:
390
#13 0x00339701 in _vmt_proc (thread_arg=0x96d0250) at vmt.c:347
#14 0x002afdec in start_thread () from /lib/tls/libpthread.so.0
#15 0x00603a2a in clone () from /lib/tls/libc.so.6
===================================================================
 
F

Fredrik Lundh

grbgooglefan said:
I have a following C++ code which uses PyObject_CallObject to evaluate
expressions dynamically. This code sets the input parameters for the
function also dynamically. After calling this function 4 times (with
these shown values), PyObject_CallObject causes application to crash
in frame_dealloc.
1) Can some one please help me understand why is this crash happening
in frame_dealloc & how to solve it?
2) Is there anything wrong I am doing about incrementing or
decrementing the reference counts of the object passed to
PyObject_CallObject?

if something crashes after a while, it's almost always a reference count
error.
default:
printf("Unknown data type [%d] for %s\n",ndtyp,pEvalFunc-
pExprVarsArray[nCtr].szVarName);
}

what's val set to if this happens?
if(!val){
ret = -1;
printf("Failed to convert %d %s to PyObject\n",ndtyp,pEvalFunc-
pExprVarsArray[nCtr].szVarName); fflush(stdout);
Py_XDECREF(pTuple);
break;
}
PyTuple_SetItem(pTuple, nCtr, val);
Py_XDECREF(val);
}

PyTuple_SetItem "steals" a reference

http://docs.python.org/api/refcountDetails.html

so you shouldn't DECREF val yourself.
// all variables are set, call Python function
Py_XINCREF(pTuple);

this isn't necessary, and will (most likely) result in a leak.
PyObject *pResult = PyObject_CallObject(pEvalFunc-
Py_XDECREF(pTuple);

if(PyErr_Occurred()){
PyErr_Print();
} else {
char* plevel = NULL;
if(NULL != (plevel = PyString_AsString(pResult))){
ret = 0;
sprintf(szEvalResult,"%s",plevel);

shouldn't you check the size of plevel here, before copying it to
szEvalResult? (and what's wrong with using strcpy to do the copy,
btw?)

</F>
 
P

Phil Thompson

I have a following C++ code which uses PyObject_CallObject to evaluate
expressions dynamically. This code sets the input parameters for the
function also dynamically. After calling this function 4 times (with
these shown values), PyObject_CallObject causes application to crash
in frame_dealloc.
1) Can some one please help me understand why is this crash happening
in frame_dealloc & how to solve it?
2) Is there anything wrong I am doing about incrementing or
decrementing the reference counts of the object passed to
PyObject_CallObject?
Yes.

3) Is it because of the big value (2299265.500000) I am trying to
convert from double to float using PyFloat_FromDouble?

//========================= code reduced for readability
===============
switch(ndtyp){
case(INT_T):
{
printf("PyInt_FromLong val %d, var %s
\n",inputVar.nionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
val = PyInt_FromLong(inputVar.nionum);
break;
}
case(LONG_T):
{
printf("PyLong_FromLong val %ld, var %s
\n",inputVar.lionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
val = PyLong_FromLong(inputVar.lionum);
break;
}
case(FLOAT_T):
{
printf("PyFloat_FromDouble val %f, var %s
\n",inputVar.fionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
val = PyFloat_FromDouble(inputVar.fionum);
break;
}
case(DOUBLE_T):
{
printf("PyFloat_FromDouble val %f, var %s
\n",inputVar.dionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
val = PyFloat_FromDouble(inputVar.dionum);
break;
}
case(STRING_T):
{
printf("PyString_FromString val %s, var %s
\n",inputVar.ioString,pEvalFunc->pExprVarsArray[nCtr].szVarName);
val = PyString_FromString(inputVar.ioString);
break;
}
default:
printf("Unknown data type [%d] for %s\n",ndtyp,pEvalFunc-
pExprVarsArray[nCtr].szVarName);

}
if(!val){
ret = -1;
printf("Failed to convert %d %s to PyObject\n",ndtyp,pEvalFunc-
pExprVarsArray[nCtr].szVarName); fflush(stdout);

Py_XDECREF(pTuple);
break;
}
PyTuple_SetItem(pTuple, nCtr, val);
Py_XDECREF(val);

Don't do this - PyTuple_SetItem() steals a reference to val.
}
// all variables are set, call Python function
Py_XINCREF(pTuple);

Why do this?
PyObject *pResult = PyObject_CallObject(pEvalFunc-


Py_XDECREF(pTuple);

Why do this?
if(PyErr_Occurred()){
PyErr_Print();
} else {
char* plevel = NULL;
if(NULL != (plevel = PyString_AsString(pResult))){
ret = 0;
sprintf(szEvalResult,"%s",plevel);
}
}
Py_XDECREF(pResult);

pTuple will now have the same number of references as when you started the
above code, so you may want to Py_DECREF() it.

Phil
 
G

grbgooglefan

I have a following C++ code which uses PyObject_CallObject to evaluate
expressions dynamically. This code sets the input parameters for the
function also dynamically. After calling this function 4 times (with
these shown values), PyObject_CallObject  causes application to crash
in frame_dealloc.
1) Can some one please help me understand why is this crash happening
in frame_dealloc & how to solve it?
2) Is there anything wrong I am doing about incrementing or
decrementing the reference counts of the object passed to
PyObject_CallObject?
Yes.





3) Is it because of the big value (2299265.500000) I am trying to
convert from double to float using PyFloat_FromDouble?
//========================= code reduced for readability
===============
switch(ndtyp){
     case(INT_T):
         {
         printf("PyInt_FromLong val %d, var %s
\n",inputVar.nionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
         val = PyInt_FromLong(inputVar.nionum);
         break;
         }
      case(LONG_T):
         {
         printf("PyLong_FromLong val %ld, var %s
\n",inputVar.lionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
         val = PyLong_FromLong(inputVar.lionum);
         break;
         }
      case(FLOAT_T):
         {
         printf("PyFloat_FromDouble val %f, var %s
\n",inputVar.fionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
         val = PyFloat_FromDouble(inputVar.fionum);
         break;
         }
      case(DOUBLE_T):
         {
         printf("PyFloat_FromDouble val %f, var %s
\n",inputVar.dionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
         val = PyFloat_FromDouble(inputVar.dionum);
         break;
         }
       case(STRING_T):
         {
         printf("PyString_FromString val %s, var %s
\n",inputVar.ioString,pEvalFunc->pExprVarsArray[nCtr].szVarName);
         val = PyString_FromString(inputVar.ioString);
         break;
         }
       default:
         printf("Unknown data type [%d] for %s\n",ndtyp,pEvalFunc-
pExprVarsArray[nCtr].szVarName);

}
if(!val){
   ret = -1;
   printf("Failed to convert %d %s to PyObject\n",ndtyp,pEvalFunc-
pExprVarsArray[nCtr].szVarName); fflush(stdout);
   Py_XDECREF(pTuple);
   break;
}
  PyTuple_SetItem(pTuple, nCtr, val);
  Py_XDECREF(val);

Don't do this - PyTuple_SetItem() steals a reference to val.
}
// all variables are set, call Python function
Py_XINCREF(pTuple);

Why do this?
  PyObject *pResult = PyObject_CallObject(pEvalFunc-

Py_XDECREF(pTuple);

Why do this?
if(PyErr_Occurred()){
 PyErr_Print();
} else {
      char* plevel = NULL;
      if(NULL != (plevel = PyString_AsString(pResult))){
        ret = 0;
        sprintf(szEvalResult,"%s",plevel);
      }
}
Py_XDECREF(pResult);

pTuple will now have the same number of references as when you started the
above code, so you may want to Py_DECREF() it.

Phil- Hide quoted text -

- Show quoted text -

Thanks for all the responses.
These help me.
I could simulate this crash in my small test program & I think (I
could be wrong also) it is because of extraneous Py_XDECREF of
"PyObject *val" which I am using to convert variables to tuple.
When I change the code to simple do like this, it works fine.
PyTuple_SetItem(pytuple,0,PyLong_FromLong(size));
PyTuple_SetItem(pytuple,1,PyLong_FromLong(maxvol));
PyTuple_SetItem(pytuple,2,PyFloat_FromDouble(adv));
 
G

grbgooglefan

I have a following C++ code which uses PyObject_CallObject to evaluate
expressions dynamically. This code sets the input parameters for the
function also dynamically. After calling this function 4 times (with
these shown values), PyObject_CallObject  causes application to crash
in frame_dealloc.
1) Can some one please help me understand why is this crash happening
in frame_dealloc & how to solve it?
2) Is there anything wrong I am doing about incrementing or
decrementing the reference counts of the object passed to
PyObject_CallObject?
3) Is it because of the big value (2299265.500000) I am trying to
convert from double to float using PyFloat_FromDouble?
//========================= code reduced for readability
===============
switch(ndtyp){
     case(INT_T):
         {
         printf("PyInt_FromLong val %d, var %s
\n",inputVar.nionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
         val = PyInt_FromLong(inputVar.nionum);
         break;
         }
      case(LONG_T):
         {
         printf("PyLong_FromLong val %ld, var %s
\n",inputVar.lionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
         val = PyLong_FromLong(inputVar.lionum);
         break;
         }
      case(FLOAT_T):
         {
         printf("PyFloat_FromDouble val %f, var %s
\n",inputVar.fionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
         val = PyFloat_FromDouble(inputVar.fionum);
         break;
         }
      case(DOUBLE_T):
         {
         printf("PyFloat_FromDouble val %f, var %s
\n",inputVar.dionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);
         val = PyFloat_FromDouble(inputVar.dionum);
         break;
         }
       case(STRING_T):
         {
         printf("PyString_FromString val %s, var %s
\n",inputVar.ioString,pEvalFunc->pExprVarsArray[nCtr].szVarName);
         val = PyString_FromString(inputVar.ioString);
         break;
         }
       default:
         printf("Unknown data type [%d] for %s\n",ndtyp,pEvalFunc-
pExprVarsArray[nCtr].szVarName);
}
if(!val){
   ret = -1;
   printf("Failed to convert %d %s to PyObject\n",ndtyp,pEvalFunc-
pExprVarsArray[nCtr].szVarName); fflush(stdout);
   Py_XDECREF(pTuple);
   break;
}
  PyTuple_SetItem(pTuple, nCtr, val);
  Py_XDECREF(val);
Don't do this - PyTuple_SetItem() steals a reference to val.
Why do this?
Why do this?
pTuple will now have the same number of references as when you started the
above code, so you may want to Py_DECREF() it.
Phil- Hide quoted text -
- Show quoted text -

Thanks for all the responses.
These help me.
I could simulate this crash in my small test program & I think (I
could be wrong also) it is because of extraneous Py_XDECREF of
"PyObject *val" which I am using to convert variables to tuple.
When I change the code to simple do like this, it works fine.
            PyTuple_SetItem(pytuple,0,PyLong_FromLong(size));
            PyTuple_SetItem(pytuple,1,PyLong_FromLong(maxvol));
            PyTuple_SetItem(pytuple,2,PyFloat_FromDouble(adv));- Hide quoted text -

- Show quoted text -

Now my new code looks like this.
Do you think this is correct way to handle ref counts? Do you forsee
any issues of memory leaks, etc. here?

//
================================================================================
switch(ndtyp){
case(INT_T):
//printf("PyInt_FromLong val %d, var %s
\n",inputVar.nionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);

PyTuple_SetItem(pTuple,nCtr,PyInt_FromLong(inputVar.nionum));
break;
case(LONG_T):
//printf("PyLong_FromLong val %ld, var %s
\n",inputVar.lionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);

PyTuple_SetItem(pTuple,nCtr,PyLong_FromLong(inputVar.lionum));
break;
case(FLOAT_T):
//printf("PyFloat_FromDouble val %f, var %s
\n",inputVar.fionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);

PyTuple_SetItem(pTuple,nCtr,PyFloat_FromDouble(inputVar.fionum));
break;
case(DOUBLE_T):
//printf("PyFloat_FromDouble val %f, var %s
\n",inputVar.dionum,pEvalFunc->pExprVarsArray[nCtr].szVarName);

PyTuple_SetItem(pTuple,nCtr,PyFloat_FromDouble(inputVar.dionum));
break;
case(STRING_T):
//printf("PyString_FromString val %s, var %s
\n",inputVar.ioString,pEvalFunc->pExprVarsArray[nCtr].szVarName);

PyTuple_SetItem(pTuple,nCtr,PyString_FromString(inputVar.ioString));
break;
default:
printf("Unknown data type [%d] for %s
\n",ndtyp,pEvalFunc->pExprVarsArray[nCtr].szVarName);
bUnknownDataType = true;
break;
}
if(bUnknownDataType){ // got an unknown data type for a variable
ret = -1;
break;
}
}
// all variables are set, call Python function
if(ret == 0){
PyObject *pResult = PyObject_CallObject(pEvalFunc-
pPyEvalFunction,pTuple);

if(PyErr_Occurred()){
ret = -1;
printf("error occured in PyObject_CallObject\n");
PyErr_Print();
} else {
char* plevel = NULL;
if(NULL != (plevel = PyString_AsString(pResult))){
ret = 0;
strncpy(szEvalResult,plevel,strlen(plevel));
printf("Final result %s\n",szEvalResult);
} else {
printf("PyObject_CallObject returned NULL\n");
ret = -1;
}
}
Py_XDECREF(pResult);
Py_XDECREF(pTuple);
//
================================================================================
 
F

Fredrik Lundh

grbgooglefan said:
char* plevel = NULL;
if(NULL != (plevel = PyString_AsString(pResult))){
ret = 0;
strncpy(szEvalResult,plevel,strlen(plevel));

strncpy doesn't check the size of the target buffer, so that's no
different from just doing strcpy(szEvalResult, plevel). or in other
words, it's still trivial to crash your program simply by returning
too much data from the Python code.

</F>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top