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

Started by Pfuntner, Johnover 12 years ago3 messagesgeneral
Jump to latest
#1Pfuntner, John
John.Pfuntner@Teradata.com

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?

--
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general

#2Stephen Woodbridge
woodbri@swoodbridge.com
In reply to: Pfuntner, John (#1)
Re: Do I have to free storage in a UDF if I raise an error?

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.

-Steve

--
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general

#3Michael Paquier
michael@paquier.xyz
In reply to: Stephen Woodbridge (#2)
Re: Do I have to free storage in a UDF if I raise an error?

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

--
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general