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  | nullid
 13 | 2  | admin
 16 | 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)