2012-01-04 4 views
2

私はV1呼び出し規約を使用して、PGのC拡張ライブラリを作成しました。集計関数を呼び出すと、postgresサーバープロセスがクラッシュします。私はgdbを使ってサーバプロセスをデバッグし、Seg-Vがどこにあるのかを調べました。PostgreSQL集約関数が外部のCライブラリ(クラッシュサーバ)に実装されています

無効なアドレスにアクセスしようとしたために発生します。私が理解していないことは、メモリが以前に正常に割り当てられたことです。しかし、コードのコメントから判断すると、メモリはまだ使用中に収穫/解放されていると思われます。私はポストグルの内部について十分に分かっていませんが、これは問題の原因と思われます。

クラッシュを引き起こし、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

答えて

1

ですパタパタあなたはARRAY_AGG実装http://doxygen.postgresql.org/array__userfuncs_8c_source.html

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 } 

これは9.1のためにある中で見つけることができます - あなたは、古いバージョンを使用している場合は、関連するソースコードに見えます。

+0

backend dbが8.4であることを忘れていました。しかし以前のバージョンのPGでも動作していました。 8.4の関連文書のリンクを投稿できますか?あなたがリンクを提供した文書は、9.1への参照をしません - それは8.4のコードのために使用できますか? –

+0

http://archives.postgresql.org/pgsql-committers/2008-11/msg00159.php http://anoncvs.postgresql.org/cvsweb.cgi/pgsql/src/backend/utils/adt/array_userfuncs.c? r1 = 1.23&r2 = 1.24これは8.4パッチです –

関連する問題