Обсуждение: Do I have to free storage in a UDF if I raise an error?

Поиск
Список
Период
Сортировка

Do I have to free storage in a UDF if I raise an error?

От
"Pfuntner, John"
Дата:
If I've done a palloc() to get storage inside a user-defined function and raise an error using ereport(),  should I be
usingpfree() to release the storage before the ereport()? 

Consider this example in C:

PG_FUNCTION_INFO_V1(Example);
Datum
Example(PG_FUNCTION_ARGS) {
  VarChar* pstring=PG_GETARG_VARCHAR_P(0);
  VarChar* ret=NULL;

  int len = VARSIZE(pstring) - VARHDRSZ;
  char *string=palloc(len+1);
  memcpy(string, VARDATA(pstring), len);
  string[len] = '\0';

  /* ... */

  if ( /* some bad condition */ ) {
    ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("some bad condition occurred!")));
  }

  /* ... */

  pfree(string);

  if (ret == NULL)
    PG_RETURN_NULL();
  else
    PG_RETURN_VARCHAR_P(ret);
}

I only have the pfree() at the end before the return if there is no error.  If I fail to call pfree() before ereport(),
doI have a memory leak? 


Re: Do I have to free storage in a UDF if I raise an error?

От
Stephen Woodbridge
Дата:
On 1/6/2014 10:00 AM, Pfuntner, John wrote:
> If I've done a palloc() to get storage inside a user-defined function and raise an error using ereport(),  should I
beusing pfree() to release the storage before the ereport()? 
>
> Consider this example in C:
>
> PG_FUNCTION_INFO_V1(Example);
> Datum
> Example(PG_FUNCTION_ARGS) {
>    VarChar* pstring=PG_GETARG_VARCHAR_P(0);
>    VarChar* ret=NULL;
>
>    int len = VARSIZE(pstring) - VARHDRSZ;
>    char *string=palloc(len+1);
>    memcpy(string, VARDATA(pstring), len);
>    string[len] = '\0';
>
>    /* ... */
>
>    if ( /* some bad condition */ ) {
>      ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("some bad condition occurred!")));
>    }
>
>    /* ... */
>
>    pfree(string);
>
>    if (ret == NULL)
>      PG_RETURN_NULL();
>    else
>      PG_RETURN_VARCHAR_P(ret);
> }
>
> I only have the pfree() at the end before the return if there is no error.  If I fail to call pfree() before
ereport(),do I have a memory leak? 

No, this is why it is important to use palloc and malloc.

-Steve



Re: Do I have to free storage in a UDF if I raise an error?

От
Michael Paquier
Дата:
On Tue, Jan 7, 2014 at 12:46 AM, Stephen Woodbridge
<woodbri@swoodbridge.com> wrote:
> On 1/6/2014 10:00 AM, Pfuntner, John wrote:
>>
>> If I've done a palloc() to get storage inside a user-defined function and
>> raise an error using ereport(),  should I be using pfree() to release the
>> storage before the ereport()?
>>
>> Consider this example in C:
>>
>> PG_FUNCTION_INFO_V1(Example);
>> Datum
>> Example(PG_FUNCTION_ARGS) {
>>    VarChar* pstring=PG_GETARG_VARCHAR_P(0);
>>    VarChar* ret=NULL;
>>
>>    int len = VARSIZE(pstring) - VARHDRSZ;
>>    char *string=palloc(len+1);
>>    memcpy(string, VARDATA(pstring), len);
>>    string[len] = '\0';
>>
>>    /* ... */
>>
>>    if ( /* some bad condition */ ) {
>>      ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("some bad
>> condition occurred!")));
>>    }
>>
>>    /* ... */
>>
>>    pfree(string);
>>
>>    if (ret == NULL)
>>      PG_RETURN_NULL();
>>    else
>>      PG_RETURN_VARCHAR_P(ret);
>> }
>>
>> I only have the pfree() at the end before the return if there is no error.
>> If I fail to call pfree() before ereport(), do I have a memory leak?
>
>
> No, this is why it is important to use palloc and malloc.
palloc allocates memory in the context of a transaction, meaning that
it will be automatically freed when transaction finishes by either a
commit or an abort. When calling ereport the transaction will be
automatically aborted, hence free'ing the memory.  Have a look here
for more details:
http://www.postgresql.org/docs/devel/static/xfunc-c.html#AEN54284
Regards,
--
Michael