Subject RE: [firebird-support] Memory allocation problem in Firebird 2.1.2
Author Calin Pirtea
Hi Dmitry,



Thanks for your response. I double checked our UDF and it was using the
wrong memory allocation inside the UDF. I fixed it and it works
perfectly.



This means we now have a work around and I can breathe... J

I am still interested in paying a small amount for a developer to work
towards fixing this inside the engine if you do consider it as important
as I do...



Thanks a million Dmitry.





Here is the code of my UDF written in Delphi 2007:



MaxVarCharSize = 32764;

TVarCharData = array[1..MaxVarCharSize] of char;



TVarChar = record

length: smallint;

data: TVarCharData;

end;

PVarChar = ^TVarChar;



function MakeVarChar(aStr: string; iLen: integer = 254): PVarChar;

var

LLen: longint;

MaxLen: integer;

Str: string;

begin

{The maximum length for the varchar we are going to allow is the
smaller of

1. the iLen argument passed to the function.

2. the maximum size allowed in memory for our own definition of
varchars}

MaxLen := Min(iLen, Pred(SizeOf(TVarCharData)));

Str := aStr;

LLen := Length(Str);

if LLen > MaxLen then

begin

LLen := MaxLen;

Str := Copy(aStr, 1, MaxLen);

end;

Result := ib_util_malloc(MaxLen + 3);

EmptyMem(Result, MaxLen + 3);

Result.Length := LLen;



if LLen > 0 then

BlockCopyMem(@Str[1], @..., LLen);

end;



function BlobAsString(Blob: PBlob): string;

var

bytes_read, bytes_left, total_bytes_read: Longint;

st: string;

begin

result := '';

if (not Assigned(Blob)) or

(not Assigned(Blob^.BlobHandle)) then

exit;

with Blob^ do

begin

bytes_left := TotalSize; // I have TotalSize bytes to read.

if (bytes_left = 0) then // if I've nothing to copy, exit.

exit;

SetLength(st, TotalSize);

total_bytes_read := 0; // total bytes read is 0.

repeat

// Using BlobHandle, store at most "bytes_left" bytes in

// the buffer starting where I last left off

GetSegment(BlobHandle, @st[total_bytes_read + 1], bytes_left,
bytes_read);

bytes_read := (bytes_read and $FFFF);

// Increment total_bytes_read by the number of bytes actually
read.

Inc(total_bytes_read, bytes_read);

// Decrement bytes_left by the number of bytes actually read.

Dec(bytes_left, bytes_read);

until bytes_left <= 0;

end;

Result := st;

end;



function CU_BLOBSUBSTRING(aBlob: PBlob; iFrom: Psmallint; iFor:
Psmallint): PVarChar;

var

aFrom, aFor: integer;

aString, aStr: string;

begin

Result := nil;

if (not Assigned(aBlob)) or (not Assigned(aBlob^.BlobHandle)) then

exit;

if (iFrom = nil) or (iFor = nil) then

exit;



aFrom := iFrom^;

aFor := iFor^;

aString := BlobAsString(aBlob);

if aFor > 32764 then

aFor := 32764;

if (aFrom + aFor - 1) > Length(aString) then

aFor := (Length(aString) - aFrom) + 1;

{If the parameters passed are outside the string then return an empty
string.}

if (aFor < 1) or (aFrom > Length(aString)) then

begin

aFor := 0;

aFrom := 1;

end;

try

SetLength(aStr, aFor);

if aFor > 0 then

BlockCopyMem(@aString[aFrom], @aStr[1], aFor);

except

end;

Result := MakeVarChar(aStr);

end;



The error in the UDF was that instead of SetLength, the programmer
incorrectly used SetString which causes a memory leak outside Firebird
memory manager's control.



Cheers,



Calin Pirtea

Communicare Development Team

Communicare Systems Pty Ltd

Tel: 9332 2433 Fax: 9310 1516

calin.pirtea@...
<mailto:calin.pirtea@...>

www.communicaresystems.com.au <http://www.communicaresystems.com.au>



Communicare Systems advises that this email account is not continuously
monitored. Please forward any Helpdesk enquiries to our monitored
address helpdesk@...
<mailto:helpdesk@...> and note that urgent
matters must be advised by telephone. This message, and any
attachments, are intended only for the use of the individual or entity
to which it is addressed and may contain information that is
confidential. Any unauthorised use, disclosure, reproduction or
distribution of this message and its attachments is prohibited. This
message is forwarded from an individual and does not necessarily
represent the views of Communicare Systems. If you have received this
message in error kindly notify the sender and then delete the contents.



From: firebird-support@yahoogroups.com
[mailto:firebird-support@yahoogroups.com] On Behalf Of Dmitry Yemanov
Sent: Tuesday, 18 August 2009 3:52 PM
To: firebird-support@yahoogroups.com
Subject: Re: [firebird-support] Memory allocation problem in Firebird
2.1.2





Calin Pirtea wrote:
>
> That was my first try. Unfortunately it is a lot worse. It allocates
2GB
> of RAM and that keeps on working corrupting memory. Scary stuff.

Hmmm. I draftly tried that before suggesting and the memory of the
fbserver process didn't grow during the query execution. Maybe it's
worth discussing your UDF code?

Dmitry





[Non-text portions of this message have been removed]