在外部C库(服务器)中实现的PostgreSQL聚合函数

在外部C库(服务器)中实现的PostgreSQL聚合函数,c,postgresql,C,Postgresql,我使用V1调用约定为PG编写了一个C扩展库。当我调用聚合函数时,它会使postgres服务器进程崩溃。我已经使用gdb调试了服务器进程,并找到了Seg-V发生的位置 这是由于试图访问无效地址造成的。但我不明白的是,内存是在早些时候成功分配的。但从代码中的注释判断,我怀疑内存在使用时正在被获取/释放。我对博士后的内部情况了解不够,但这似乎是问题的可能原因 我已经包含了导致崩溃的函数的代码,并突出显示了导致Seg-V的行。我是否使用正确的参数调用MemoryContextAlloc static P

我使用V1调用约定为PG编写了一个C扩展库。当我调用聚合函数时,它会使postgres服务器进程崩溃。我已经使用gdb调试了服务器进程,并找到了Seg-V发生的位置

这是由于试图访问无效地址造成的。但我不明白的是,内存是在早些时候成功分配的。但从代码中的注释判断,我怀疑内存在使用时正在被获取/释放。我对博士后的内部情况了解不够,但这似乎是问题的可能原因

我已经包含了导致崩溃的函数的代码,并突出显示了导致Seg-V的行。我是否使用正确的参数调用MemoryContextAlloc

static PGARRAY *GetPGArray(int4 state, int fAdd);    
static PGARRAY *ShrinkPGArray(PGARRAY * p);

Datum       float8_agg_state(PG_FUNCTION_ARGS);    
Datum       float8_agg_final_count(PG_FUNCTION_ARGS);    
Datum       float8_agg_final_array(PG_FUNCTION_ARGS);    
Datum       float8_enum(PG_FUNCTION_ARGS);        

PG_FUNCTION_INFO_V1(float8_agg_state);    
PG_FUNCTION_INFO_V1(float8_agg_final_count);    
PG_FUNCTION_INFO_V1(float8_agg_final_array);    
PG_FUNCTION_INFO_V1(float8_enum);

/*    
 * Manage the aggregation state of the array    
 *    
 * Need to specify a suitably long-lived memory context, or it will vanish!    
 * PortalContext isn't really right, but it's close enough (famous last words ...).    
 */

static PGARRAY *    
GetPGArray(int4 state, int fAdd)    
{    
    PGARRAY    *p = (PGARRAY *) state;

    if (!state)    
    {    
        /* New array */    
        int cb = PGARRAY_SIZE(START_NUM);       

        p = (PGARRAY *) MemoryContextAlloc(PortalContext, cb);    
        p->a.vl_len_ = cb;    
        p->a.ndim = 0;    
        p->a.dataoffset = 0;

#ifndef PG_7_2    
        p->a.elemtype = FLOAT8OID;    
#endif

        p->items = 0;    
        p->lower = START_NUM; 
    }
    else if (fAdd)    
    {       
           /* Ensure array has space */

           /* SEG-V fault on the line below */
        if (p->items >= p->lower)    
        {    
            PGARRAY *pn;    
            int n = p->lower + p->lower;   
            int cbNew = PGARRAY_SIZE(n);

            pn = (PGARRAY *) repalloc(p, cbNew);    
            pn->a.vl_len_ = cbNew;    
            pn->lower = n;    
            return pn;   
        }    
    }

    return p;    
}
有人知道为什么代码是SG-V吗

[[编辑]]


我的后端PG服务器是v8.4.9

应该有更多的问题-错误的注册、错误的返回数据格式、错误的返回数据内存上下文-您可以在array_agg实现中找到良好的模式


这是针对9.1的-如果您有旧版本,请查看相关的源代码。

我忘了提到我的后端db was 8.4。但用于PG早期版本的代码。你能给8.4的相关文件贴个链接吗?。您提供链接的文档没有参考9.1-它可以用于8.4代码吗?这是8.4补丁
00477 array_agg_transfn(PG_FUNCTION_ARGS)
00478 {
00479     Oid         arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1);
00480     MemoryContext aggcontext;
00481     ArrayBuildState *state;
00482     Datum       elem;
00483 
00484     if (arg1_typeid == InvalidOid)
00485         ereport(ERROR,
00486                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00487                  errmsg("could not determine input data type")));
00488 
00489     if (!AggCheckCallContext(fcinfo, &aggcontext))
00490     {
00491         /* cannot be called directly because of internal-type argument */
00492         elog(ERROR, "array_agg_transfn called in non-aggregate context");
00493     }
00494 
00495     state = PG_ARGISNULL(0) ? NULL : (ArrayBuildState *) PG_GETARG_POINTER(0);
00496     elem = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
00497     state = accumArrayResult(state,
00498                              elem,
00499                              PG_ARGISNULL(1),
00500                              arg1_typeid,
00501                              aggcontext);
00502 
00503     /*
00504      * The transition type for array_agg() is declared to be "internal", which
00505      * is a pass-by-value type the same size as a pointer.  So we can safely
00506      * pass the ArrayBuildState pointer through nodeAgg.c's machinations.
00507      */
00508     PG_RETURN_POINTER(state);
00509 }