this source is strange,
 
when I uncomment code(1), and compile, and, run query
 
d_cppschool=>
SELECT * FROM UC_ExecWithNo('SELECT I_IDNum,I_UserID FROM DI_ID',10,10,3) as T(T1 int,T2 bigint,T3 CHAR(20))
 
and I get result :
 
WARNING: transaction left non-empty SPI stack Hint: Check for missing "SPI_finish" calls.t1 | t2 | t3
----+----+----------------------10 | 0  | nullid13 | 2  | admin16 | 1  | test(3 rows)"
but when I comment code(1), and compile, and, run the query
and I get the strange result :  psql process die !!
 
I Don't know why.
Please help me to solve the problem.(Sorry, I'm not good at english speeking)
 
code(1) is "::SPI_finish()" 
Thank for your advices in advance.
The Detail is below : 
    PG_FUNCTION_INFO_V1(uc_execwithno); // add no field to table
   Datum uc_execwithno(PG_FUNCTION_ARGS)   {      class CMyData // context       {         public:
         SPITupleTable*  GP_TupleTable;           int /********/  GI_FieldCount;           int /********/  GI_StartNum  ;
           CMyData()           {               GP_TupleTable=0;               GI_FieldCount=0;               GI_StartNum  =0;           }           //end CMyData()       };       //end class CMyData
       if(GB_DoShowInfoLog==true)           elog(INFO, "UC_ExecWithNo Start");       //endif
       text* pQuery_T=PG_GETARG_TEXT_P(0);       int   AI_LimitCnt=PG_GETARG_INT32 (1);       int   AI_StartNum=PG_GETARG_INT32 (2);       int   AI_SkipNum =PG_GETARG_INT32 (3);
       int      VI_AttCnt =0;       CMyData* pCMyData  =0;
       TupleDesc       pTupleDesc ;       SPITupleTable*  pTupleTable;
       TupleDesc           TupDescNew  ;       MemoryContext       OldContext  ;       AttInMetadata*      pAttInMeta  ;       FuncCallContext*    pFuncCTX    ;
       if (SRF_IS_FIRSTCALL())       {           char* AP_Query=NsPgsql::NewAlloc(pQuery_T);
           int VI_Result=0;           int VI_RowCnt=0;
           pFuncCTX = SRF_FIRSTCALL_INIT();           OldContext = ::MemoryContextSwitchTo(pFuncCTX->multi_call_memory_ctx);
           if ((VI_Result = ::SPI_connect()) < 0)           {               /* internal error */               elog(ERROR, "internal error : ISPI_connect returned =%d", VI_Result);
               SRF_RETURN_DONE(pFuncCTX);           }           //endif
           VI_Result=::SPI_execute(AP_Query,true/*AB_DoReadOnly*/,AI_LimitCnt);           VI_RowCnt=::SPI_processed  ;
           pfree(AP_Query);
           if(VI_Result!=SPI_OK_SELECT || VI_RowCnt<1)           {               ::SPI_finish();
               SRF_RETURN_DONE(pFuncCTX);           }           else           {               pFuncCTX->max_calls=VI_RowCnt ;
               pTupleTable = ::SPI_tuptable;               pTupleDesc  = ::SPI_tuptable->tupdesc;
               VI_AttCnt=pTupleDesc->natts;           }           //endif
           TupDescNew = ::CreateTemplateTupleDesc(VI_AttCnt+1, false/*bool hasoid*/);
           ::TupleDescInitEntry(TupDescNew, 1/*attnum*/, "no"/*attname*/, INT4OID/*oidtypeid*/,-1/*typmod*/, 0/*attdim*/);
           FormData_pg_attribute* pFormDataAtt;
           for(int i=1;i<=VI_AttCnt;++i)           {               pFormDataAtt=pTupleDesc->attrs[i-1];
               // cf) char* SPI_fname(TupleDesc rowdesc, int colnumber)
               ::TupleDescInitEntry(TupDescNew, (AttrNumber)(i+1), SPI_fname(pTupleDesc,i), pFormDataAtt->atttypid,pFormDataAtt->atttypmod, pFormDataAtt->attndims);           }           //endfor
           // generate attribute metadata needed later to produce tuples from raw
           pAttInMeta = ::TupleDescGetAttInMetadata(TupDescNew);           pFuncCTX->attinmeta = pAttInMeta;
           /* Save spi data for use across calls */
           CMyData* pCMyData=(CMyData*)palloc(sizeof(CMyData));
           pCMyData->GP_TupleTable=pTupleTable ;           pCMyData->GI_FieldCount=VI_AttCnt   ;           pCMyData->GI_StartNum  =AI_StartNum ;
           pFuncCTX->user_fctx=pCMyData ;
           ::MemoryContextSwitchTo(OldContext);       }       //end if (SRF_IS_FIRSTCALL())
       pFuncCTX = SRF_PERCALL_SETUP();
       pAttInMeta  = pFuncCTX->attinmeta;       pCMyData    =(CMyData*)(pFuncCTX->user_fctx);
       VI_AttCnt   =pCMyData->GI_FieldCount;       pTupleTable =pCMyData->GP_TupleTable;       AI_StartNum =pCMyData->GI_StartNum  ;
       pTupleDesc  =pTupleTable->tupdesc   ;
       pCMyData->GI_StartNum += AI_SkipNum ;
       if (pFuncCTX->call_cntr < pFuncCTX->max_calls)       {           if(GB_DoShowInfoLog==true)               elog(INFO, "UC_ExecWithNo Call Num=%d",pFuncCTX->call_cntr);           //endif
           char**      ppValues    ;           HeapTuple   TupleNewObj ;           Datum       DatumResult ;
           const int CI_IntAllocLen=12;
           ppValues    = (char **)palloc((VI_AttCnt+1) * sizeof(char *));           ppValues[0] = (char *) palloc(CI_IntAllocLen * sizeof(char));
           ::snprintf(ppValues[0], CI_IntAllocLen, "%d", AI_StartNum);
           HeapTuple TupleObj = pTupleTable->vals[pFuncCTX->call_cntr];
           for(int i=1;i<=VI_AttCnt;++i)           {               ppValues[i]=::SPI_getvalue(TupleObj, pTupleDesc, i);           }           //endfor
           TupleNewObj = BuildTupleFromCStrings(pAttInMeta, ppValues); /* build a tuple */           DatumResult = HeapTupleGetDatum(TupleNewObj); /* make the tuple into a datum */
           pfree(ppValues[0]);           pfree(ppValues);
           ::SPI_freetuple(TupleObj);
           SRF_RETURN_NEXT(pFuncCTX, DatumResult);       }       else       {           pfree(pCMyData);
           // ::SPI_finish(); // code(1)            SRF_RETURN_DONE(pFuncCTX);       }       //endif   }   //end Datum uc_execwithno(PG_FUNCTION_ARGS)