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