Thread: invalid memory alloc after insert with c trigger function

invalid memory alloc after insert with c trigger function

From
Dudás József
Date:
Hello Everybody!

I know that something doing wrong, but I can't find out what is it. This is a part from trigger function:

attnum[3] = SPI_fnumber( tupdesc, "arfolyam" );
datums[3] = _selectFunctionB( "SELECT ertek FROM foo WHERE parameter='rate'" ); // this come back with Datum type from select - PG_RETURN_FLOAT8( b ); is end of this function where b is double type
arfolyam = DatumGetFloat8( datums[3] );
elog( INFO, "2.5.0 arfolyam = %f", arfolyam );
if ( attnum[3] == PointerGetDatum( NULL ) ) {
   elog( ERROR, "Hianyzo arfolyam" );
   SPI_finish();
   return PointerGetDatum(NULL);
}
elog( INFO, "2.5.1 Datums[3] = %f", DatumGetFloat8( datums[3] ) );
rettuple = SPI_modifytuple( trigdata->tg_relation, tmptuple, 4, &attnum[0], &datums[0], &isNull[0] );
SPI_freetuple(tmptuple);
SPI_finish();
return PointerGetDatum( rettuple );


After insert:
INFO: string vissza : 1.000000
INFO: 2.5.0 arfolyam = 1.000000
INFO: 2.5.1 Datums[3] = 1.000000
INSERT 0 1
ELES=# SELECT * FROM pgsor;
ERROR: invalid memory alloc request size 4294967293


The datums[0 - 2] are char* / VARCHAR type. If I set SPI_modifytuple( trigdata->tg_relation, tmptuple, 3, &attnum[0], &datums[0], &isNull[0] ); than everything is OK after insert.

The question: what is wrong with converting double to Datum?

Thanks in advance!
dj

Re: invalid memory alloc after insert with c trigger function

From
Tom Lane
Date:
=?ISO-8859-2?Q?Dud=E1s_J=F3zsef?= <dj1999@freemail.hu> writes:
> I know that something doing wrong, but I can't find out what is it.

Getting a stack trace from the point of the errfinish call would
probably help narrow it down.  One thing that's not clear is whether
SPI_modifytuple itself is failing (have you checked all the *other*
arguments you're passing it?) or whether it happens later.

            regards, tom lane

Re: invalid memory alloc after insert with c trigger function

From
Dudás József
Date:
Thanks for your reply!
I was run gdb and errfinish but didn't get much help because I write to
list.
Yes the first datas ( datums[0-2] ) are char* / VARCHAR types and if I
call SPI_modifytuple( ( trigdata->tg_relation, tmptuple, 3, &attnum[0],
&datums[0], &isNull[0] ) than everything is OK.
Just have problem with this conversion from TEXT - double - Datum (
NUMERIC ) where in TEXT is a number value forexample now the value is 1.00
> =?ISO-8859-2?Q?Dud=E1s_J=F3zsef?= <dj1999@freemail.hu> writes:
>
>> I know that something doing wrong, but I can't find out what is it.
>>
>
> Getting a stack trace from the point of the errfinish call would
> probably help narrow it down.  One thing that's not clear is whether
> SPI_modifytuple itself is failing (have you checked all the *other*
> arguments you're passing it?) or whether it happens later.
>
>             regards, tom lane
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: Don't 'kill -9' the postmaster
>
>
>


Re: invalid memory alloc after insert with c trigger function

From
Dudás József
Date:
Here is the output from gdb:

#0  errfinish (dummy=0) at elog.c:312
#1  0x0827f378 in elog_finish (elevel=20,
    fmt=0x83586d8 "invalid memory alloc request size %lu") at elog.c:937
#2  0x082983d7 in MemoryContextAlloc (context=0x843a1ac, size=4294967293)
    at mcxt.c:504
#3  0x0825751d in varcharout (fcinfo=0xbf8a1e7c) at varchar.c:447
#4  0x08281ceb in FunctionCall1 (flinfo=0x8460298, arg1=3052138532)
    at fmgr.c:1128
#5  0x0807e88f in printtup (slot=0x843d038, self=0x8405df4) at printtup.c:326
#6  0x0816b14f in ExecutorRun (queryDesc=0x8474698,
    direction=ForwardScanDirection, count=0) at execMain.c:1310
#7  0x0820059b in PortalRunSelect (portal=0x842f1f4,
    forward=<value optimized out>, count=0, dest=0x8405df4) at pquery.c:831
#8  0x08201799 in PortalRun (portal=0x842f1f4, count=2147483647,
    dest=0x8405df4, altdest=0x8405df4, completionTag=0xbf8a22e8 "")
    at pquery.c:684
#9  0x081fd150 in exec_simple_query (
    query_string=0x840593c "SELECT * FROM pgsor;") at postgres.c:939
#10 0x081fe761 in PostgresMain (argc=4, argv=<value optimized out>,
    username=0x83accdc "dj") at postgres.c:3424
#11 0x081d1cb8 in ServerLoop () at postmaster.c:2931
#12 0x081d2aa7 in PostmasterMain (argc=3, argv=0x83a78a8) at postmaster.c:963
#13 0x0818d2f0 in main (argc=3, argv=Cannot access memory at address 0x4
) at main.c:188

Hope it is verbose for you, but don't help me :)
Dudás József <dj1999@freemail.hu> writes: 
I know that something doing wrong, but I can't find out what is it.   
Getting a stack trace from the point of the errfinish call would
probably help narrow it down.  One thing that's not clear is whether
SPI_modifytuple itself is failing (have you checked all the *other*
arguments you're passing it?) or whether it happens later.
		regards, tom lane

 

Re: invalid memory alloc after insert with c trigger function

From
Gregory Stark
Date:
Dudás József <dj1999@freemail.hu> writes:

> Here is the output from gdb:
>
> #0  errfinish (dummy=0) at elog.c:312
> #1  0x0827f378 in elog_finish (elevel=20,
>    fmt=0x83586d8 "invalid memory alloc request size %lu") at elog.c:937
> #2  0x082983d7 in MemoryContextAlloc (context=0x843a1ac, size=4294967293)
>    at mcxt.c:504
> #3  0x0825751d in varcharout (fcinfo=0xbf8a1e7c) at varchar.c:447

I'm sorry I missed the beginning of this thread. This is happening on a
straight simple select of the table right? Did you already post the source of
your C trigger function? How is it constructing the original varchar datum and
doing the insert?

--
  Gregory Stark
  EnterpriseDB          http://www.enterprisedb.com


Re: invalid memory alloc after insert with c trigger function

From
Dudás József
Date:
This is the debug of last varcharout routine:

Breakpoint 1, varcharout (fcinfo=0xbf8a1e7c) at varchar.c:441
441             VarChar    *s = PG_GETARG_VARCHAR_P(0);
440     {
(gdb) print fcinfo
$25 = (FunctionCallInfo) 0xbf8a1e7c
441             VarChar    *s = PG_GETARG_VARCHAR_P(0);
446             len = VARSIZE(s) - VARHDRSZ;
(gdb) print s
$28 = (VarChar *) 0xb5ebf024
447             result = palloc(len + 1);
(gdb) print len
$29 = -4
(gdb) next
Warning:
Cannot insert breakpoint -43.
Error accessing memory address 0xf72a1719: Input/Output error

> =?ISO-8859-2?Q?Dud=E1s_J=F3zsef?= <dj1999@freemail.hu> writes:
>
>> I know that something doing wrong, but I can't find out what is it.
>>
>
> Getting a stack trace from the point of the errfinish call would
> probably help narrow it down.  One thing that's not clear is whether
> SPI_modifytuple itself is failing (have you checked all the *other*
> arguments you're passing it?) or whether it happens later.
>
>             regards, tom lane
>
>
>



Re: invalid memory alloc after insert with c trigger function

From
Dudás József
Date:
Sorry I do not understand. I did not convert float to varchar. The first
3 data are char* these conver to Datum:
attnum[0] = SPI_fnumber( tupdesc, "deviza_kod" );
datums[0] = DirectFunctionCall1(textin, CStringGetDatum(
_selectFunction( "SELECT ertek FROM foo WHERE parameter='currency'" ) ) );
if ( attnum[0] == PointerGetDatum( NULL ) ) {
      elog( ERROR, "Hianyzo deviza" );
      SPI_finish(); // zárunk
      return PointerGetDatum(NULL); // vissza
}
The 1 and 2 are same as this. But these are OK.

I have problem with NUMERIC type. Convert with this function char* to
double to Datum:

PG_FUNCTION_INFO_V1(_selectFunctionB);
Datum
_selectFunctionB( char *sql )
{
    double    b;
    int     ret, proc;

    ret = SPI_exec( sql, 0 );
    proc = SPI_processed;
    if (ret == SPI_OK_SELECT && proc > 0) {
        SPITupleTable* tuptable = SPI_tuptable;
        TupleDesc tupdesc = SPI_tuptable->tupdesc;
        HeapTuple tuple = tuptable->vals[ 0 ];
        if ( tuple ) {
            b = atof( SPI_getvalue( tuple, tupdesc, 1 ) );
        }
    }
    PG_RETURN_FLOAT8( b );
}

I call these to put Datum value to datums[3] array element:
datums[3] = _selectFunctionB( "SELECT ertek FROM foo WHERE
parameter='rate'" );

> Dudás József <dj1999@freemail.hu> writes:
>
>
>> elog( INFO, "2.5.1 Datums[3] = %f", DatumGetFloat8( datums[3] ) );
>> rettuple = SPI_modifytuple( trigdata->tg_relation, tmptuple, 4, &attnum[0],
>>
> ...
>
>> The datums[0 - 2] are char* / VARCHAR type. If I set /SPI_modifytuple(
>> trigdata->tg_relation, tmptuple, 3, &attnum[0], &datums[0], &isNull[0] ); /than
>> everything is OK after insert.
>>
>
> At what point does the float get converted to a varchar?
>
>


Re: invalid memory alloc after insert with c trigger function

From
Gregory Stark
Date:
Dudás József <dj1999@freemail.hu> writes:

> Sorry I do not understand. I did not convert float to varchar.

Well then there's some kind of miscommunication here. Your crash is happening
trying to read a varchar column later. Someone sometime is putting data into
that varchar column. I don't understand how the snippets of code handling
floats and numerics relate to the varchar that's causing your crash.


I still don't understand what you're doing and what's going on but there are a
few strange things in this code snippet:

> attnum[0] = SPI_fnumber( tupdesc, "deviza_kod" );
> datums[0] = DirectFunctionCall1(textin, CStringGetDatum( _selectFunction(
> "SELECT ertek FROM foo WHERE parameter='currency'" ) ) );
> if ( attnum[0] == PointerGetDatum( NULL ) ) {
>      elog( ERROR, "Hianyzo deviza" );
>      SPI_finish(); // zárunk
>      return PointerGetDatum(NULL); // vissza
> }

You test attnum[0] == PointerGetDatum(NULL) but attnum contains the result of
SPI_fnumber which isn't a datum at all, it's an attribute number which is an
integer. In case of error it returns SPI_ERROR_NOATTRIBUTE which is -9.

That said if your function is a function which takes PG_FUNCTION_ARGS then the
right way to return NULL is with PG_RETURN_NULL(). Merely returning a
PointerGetDatum(NULL) isn't good enough.

--
  Gregory Stark
  EnterpriseDB          http://www.enterprisedb.com


Re: invalid memory alloc after insert with c trigger function

From
Martijn van Oosterhout
Date:
Are you compiling with warnings? Because this should have blown up on
you:

On Fri, Jun 01, 2007 at 02:03:26PM +0200, Dudás József wrote:
> PG_FUNCTION_INFO_V1(_selectFunctionB);
> Datum
> _selectFunctionB( char *sql )

If you've declared your function V1 then it doesn't get passed
parameters like that. The compiler should have flagged this.

Also, can you show how you defined the function in SQL, does it match?

Have a nice day,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> From each according to his ability. To each according to his ability to litigate.

Attachment

Re: invalid memory alloc after insert with c trigger function

From
Tom Lane
Date:
=?ISO-8859-2?Q?Dud=E1s_J=F3zsef?= <dj1999@freemail.hu> writes:
> Just have problem with this conversion from TEXT - double - Datum (
> NUMERIC ) where in TEXT is a number value forexample now the value is 1.00

NUMERIC?  You didn't say anything about NUMERIC before.  The code you
posted thinks it is working with a FLOAT8 datum, which is just about
entirely unlike NUMERIC.  If you are trying to assign that to a table
column that's declared as NUMERIC, then that type mismatch is exactly
your problem.

            regards, tom lane

Re: invalid memory alloc after insert with c trigger function

From
Dudás József
Date:
Thanks your replies, these much help me. I am beginer in postgresql c
function, sorry when I wrote stupid thinks too.
This function not call from sql just from c code. So as I understand not
need PG_FUNCTION_INFO_V1 macro. It is need in case I want to call routin
direct from sql or make database function.




> Are you compiling with warnings? Because this should have blown up on
> you:
>
> On Fri, Jun 01, 2007 at 02:03:26PM +0200, Dudás József wrote:
>
>> PG_FUNCTION_INFO_V1(_selectFunctionB);
>> Datum
>> _selectFunctionB( char *sql )
>>
>
> If you've declared your function V1 then it doesn't get passed
> parameters like that. The compiler should have flagged this.
>
> Also, can you show how you defined the function in SQL, does it match?
>
> Have a nice day,
>


Re: invalid memory alloc after insert with c trigger function

From
Dudás József
Date:
Yes! You are right! Now must me find out how to convert char* to numeric
datum and double to numeric datum and numeric datum to double :)


> =?ISO-8859-2?Q?Dud=E1s_J=F3zsef?= <dj1999@freemail.hu> writes:
>
>> Just have problem with this conversion from TEXT - double - Datum (
>> NUMERIC ) where in TEXT is a number value forexample now the value is 1.00
>>
>
> NUMERIC?  You didn't say anything about NUMERIC before.  The code you
> posted thinks it is working with a FLOAT8 datum, which is just about
> entirely unlike NUMERIC.  If you are trying to assign that to a table
> column that's declared as NUMERIC, then that type mismatch is exactly
> your problem.
>
>             regards, tom lane
>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Have you searched our list archives?
>
>                http://archives.postgresql.org/
>
>
>


Re: invalid memory alloc after insert with c trigger function

From
Gregory Stark
Date:
Dudás József <dj1999@freemail.hu> writes:

> Yes! You are right! Now must me find out how to convert char* to numeric datum
> and double to numeric datum and numeric datum to double :)

If you have a char* you can usually call a types input function which is
usally "type_in" or "typein" like:
 DirectFunctionCall1(type_in, str).

However in the case of numeric you need to pass a couple extra parameters:
 DirectFunctionCall3(numeric_in, str, 0, -1 + VARHDRSZ)

To convert to a float8 datum you would use
 DirectFunctionCall1(numeric_float,num).

To convert from a Postgres float8 datum to an actual double you can just call
the macros DatumGetFloat8 and Float8GetDatum. This makes your code depend on
the internal representation of float8 as a C double but it's better than the
alternative.

--
  Gregory Stark
  EnterpriseDB          http://www.enterprisedb.com


Re: invalid memory alloc after insert with c trigger function

From
Dudás József
Date:
This is the debug of last varcharout routine:

Breakpoint 1, varcharout (fcinfo=0xbf8a1e7c) at varchar.c:441
441             VarChar    *s = PG_GETARG_VARCHAR_P(0);
440     {
(gdb) print fcinfo
$25 = (FunctionCallInfo) 0xbf8a1e7c
441             VarChar    *s = PG_GETARG_VARCHAR_P(0);
446             len = VARSIZE(s) - VARHDRSZ;
(gdb) print s
$28 = (VarChar *) 0xb5ebf024
447             result = palloc(len + 1);
(gdb) print len
$29 = -4
(gdb) next
Warning:
Cannot insert breakpoint -43.
Error accessing memory address 0xf72a1719: Input/Output error

> =?ISO-8859-2?Q?Dud=E1s_J=F3zsef?= <dj1999@freemail.hu> writes:
>
>> I know that something doing wrong, but I can't find out what is it.
>>
>
> Getting a stack trace from the point of the errfinish call would
> probably help narrow it down.  One thing that's not clear is whether
> SPI_modifytuple itself is failing (have you checked all the *other*
> arguments you're passing it?) or whether it happens later.
>
>             regards, tom lane
>
>
>


Re: invalid memory alloc after insert with c trigger function

From
Dudás József
Date:
Thank you and other helpfully peoples the interest about my first steps
in your world. I learned more than  I hope.
This function work fine now.
Can you to offer me place where I find these information, because I read
the postgresql source code to find these macros.

Regards,
Josef


> Dudás József <dj1999@freemail.hu> writes:
>
>
>> Yes! You are right! Now must me find out how to convert char* to numeric datum
>> and double to numeric datum and numeric datum to double :)
>>
>
> If you have a char* you can usually call a types input function which is
> usally "type_in" or "typein" like:
>  DirectFunctionCall1(type_in, str).
>
> However in the case of numeric you need to pass a couple extra parameters:
>  DirectFunctionCall3(numeric_in, str, 0, -1 + VARHDRSZ)
>
> To convert to a float8 datum you would use
>  DirectFunctionCall1(numeric_float,num).
>
> To convert from a Postgres float8 datum to an actual double you can just call
> the macros DatumGetFloat8 and Float8GetDatum. This makes your code depend on
> the internal representation of float8 as a C double but it's better than the
> alternative.
>
>