Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

GetMem and Strings

380 views
Skip to first unread message

David Saracini

unread,
Jul 15, 1999, 3:00:00 AM7/15/99
to
Hello All,

Record structs with strings have always confused me a little in Delphi. Can
anyone explain why if you use GetMem for a record struct and try to access a
string value you will get an AV while the same code with AllocMem will work
fine.

For Example:

Type TMyRec = record
s1 : String;
SomeInt : integer;
end;

........

procedure produce;
var p : pointer;
begin
GetMem( p, SizeOf( TMyRec ) );
TMyRec(p^).s1 := 'hello'; //<--------AV here
end;

procedure OK;
var p : pointer;
begin
p := AllocMem( SizeOf( TMyRec ) );
TMyRec(p^).s1 := 'hello';
end;

End Example----

Thanks in advance,

David Saracini

Stefan Hoffmeister (TeamB)

unread,
Jul 15, 1999, 3:00:00 AM7/15/99
to
: "David Saracini" <sara...@mtrack.com> wrote:

>why if you use GetMem for a record struct and try to access a
>string value you will get an AV while the same code with AllocMem will work
>fine.

AllocMem zero-initializes the memory, GetMem does not.

With GetMem, you simply access a garbage string. With AllocMem, you
initialize an emptry (nil) string.


--
Stefan Hoffmeister (TeamB) http://www.econos.de/
Please do apply judgement when sending email.

Philippe Ranger

unread,
Jul 15, 1999, 3:00:00 AM7/15/99
to
<<David:

procedure produce;
var p : pointer;
begin
GetMem( p, SizeOf( TMyRec ) );
TMyRec(p^).s1 := 'hello'; //<--------AV here
end;
>>

Stefen's correct, of course. But OP is built to avoid this, if you just use
it's type facilities --

procedure produce;
var p : ^TmyRec;
begin
new(p);
p.s1 := 'hello'; // no AV
end;

When you define p by the actual type it point to, New calls Initialize,
which carefully goes over the thing pointed to an nulls all strings (even in
sub-sub-structures), among other things.

PhR


David Saracini

unread,
Jul 15, 1999, 3:00:00 AM7/15/99
to
>With GetMem, you simply access a garbage string. With AllocMem, >you
>initialize an emptry (nil) string.


Why does it AV when you try to set it? Please see the Produce method is the
original posting.

David

David Saracini

unread,
Jul 15, 1999, 3:00:00 AM7/15/99
to
Philippe,

Thanks for the tip... That works great... I had used a "Typed" Pointer
with the GetMem call, but it didn't make a difference. Borland should do a
little better job documenting GetMem and recommending that developers use
New.

However, is there anything wrong with the way that I'm using AllocMem in my
original posting (except for the fact that in that simple example I'm not
call FreeMem)? In other words, do I need to go back and find all of the
places where I'm using AllocMem and change my code to use New instead?

Thanks for your help.

Best Regards,

David Saracini

Philippe Ranger <.> wrote in message <7mlf18$66...@forums.borland.com>...

Philippe Ranger

unread,
Jul 15, 1999, 3:00:00 AM7/15/99
to
<<David:

Why does it AV when you try to set it? Please see the Produce method is the
original posting.
>>

Because you are using for a string address (string var contents) a random
collection of 32 bits. Chances are it points somewhere your program does not
have access to -- Access Violation.

PhR

Philippe Ranger

unread,
Jul 15, 1999, 3:00:00 AM7/15/99
to
<<David:

Borland should do a little better job documenting GetMem and recommending
that developers use
New.
>>

Definitely!

PhR

Stefan Hoffmeister (TeamB)

unread,
Jul 16, 1999, 3:00:00 AM7/16/99
to
: "David Saracini" <sara...@mtrack.com> wrote:

>>Please see the Produce method is the
>>original posting.

I saw that.

>Why does it AV when you try to set it?

Because AnsiString is reference-counted and with every string write you
automatically get a (required) string read, too - in particular to test
whether the reference-count is > 1.

That requires access to the pointer. Since the pointer is garbage - boom.

Stefan Hoffmeister (TeamB)

unread,
Jul 16, 1999, 3:00:00 AM7/16/99
to
: "David Saracini" <sara...@mtrack.com> wrote:

>In other words, do I need to go back and find all of the
>places where I'm using AllocMem and change my code to use New instead?

It is better style and safer, yes.

Besides, if you called FreeMem on the allocated memory, you'd get some
nice memory leaks due to the highly likely fact that you'd have forgotten
to call Finalize.

David Saracini

unread,
Jul 16, 1999, 3:00:00 AM7/16/99
to
Stefan and Philippe,

Thank you both for the good advice!

David

Mikael Bak

unread,
Jul 18, 1999, 3:00:00 AM7/18/99
to
Hi Phil,
I've acually been wondering for a while now... What is really the difference
between GetMem and New ?

I always use New for creating new memory for record types, but for some
reason I always use GetMem when I want some memory for a PChar.

Should I always use New ?

/Mikael


Philippe Ranger <.> wrote in message <7mmajs$6l...@forums.borland.com>...

Robert Lee

unread,
Jul 18, 1999, 3:00:00 AM7/18/99
to
Mikael Bak wrote:

> Hi Phil,
> I've acually been wondering for a while now... What is really the difference
> between GetMem and New ?

New=GetMem+Initialize
AllocMem=GetMem+FillChar
GetMem= actually gets memory

Dispose = Finalize + FreeMem
FreeMem = frees memory


> Should I always use New ?

No, You can't set the size with New. You should probably use AllocMem. This
will pre-zero your data ensuring that you have a valid string from the start.

--
Bob Lee
High Performance Delphi - http://www.econos.com/optimize/

Loren Pechtel

unread,
Jul 18, 1999, 3:00:00 AM7/18/99
to
>I've acually been wondering for a while now... What is really the difference
>between GetMem and New ?
>
>I always use New for creating new memory for record types, but for some
>reason I always use GetMem when I want some memory for a PChar.
>
>Should I always use New ?

When the compiler can't determine the amount of memory needed,
you need GetMem.

Lord Havelock Vetinari, the patrician

unread,
Jul 19, 1999, 3:00:00 AM7/19/99
to
So if I understand correctly New gets the size of the structure and then calls
GetMem... At least as far as this goes in practice...

Bill Zissimopoulos

unread,
Jul 19, 1999, 3:00:00 AM7/19/99
to
Lord Havelock Vetinari, wrote:
> So if I understand correctly New gets the size of the structure and
> then calls GetMem... At least as far as this goes in practice...
>

New is one of these magic functions. It knows about the type and the
size of the object that you create. New calls GetMem to get the raw
memory and then calls Initialize to properly Initialize it. Always use
New/Dispose for records you allocate.

Bill


Bill Zissimopoulos

unread,
Jul 19, 1999, 3:00:00 AM7/19/99
to

Philippe Ranger

unread,
Jul 19, 1999, 3:00:00 AM7/19/99
to
<<Mikael:

I always use New for creating new memory for record types, but for some
reason I always use GetMem when I want some memory for a PChar.

Should I always use New ?
>>

Here's the entire code for _New --

------------
procedure _New{ size: Longint; typeInfo: Pointer};
asm
{ -> EAX size of object to allocate }
{ EDX pointer to typeInfo }

PUSH EDX
CALL _GetMem
POP EDX
TEST EAX,EAX
JE @@exit
PUSH EAX
CALL _Initialize
POP EAX
@@exit:
end;
------------

As you can see, the compiler replaces your call to New with one to _New, and
quite a bit of info about **the pointer type you're newing**. As long as you
use honest pointer types (no casting, etc.), the whole Delphi system works
on your side when you use New.

What actually happens is this. GetMem (ok, _GetMem) gets called on the
declared size for what the pointer points to. Then, if there's anything
special about that thing (i.e. myPointerType^), _Initialize gets called.
Initialize ensures that strings, dynArrays, variant arrays and interfaces
initialize to nil, which is absolutely essential for those things to work
correctly. The bug from not using initialize may or may not show up in
tests, because in tests you have lots of memory which happens to be zero.
Not in real life.

When Borland adds more stuff to OP, Initialize will again be added to so
that the new stuff works to.

So, the Simple-Simon reason for using New is that OP is a typed language,
and GetMem is untyped. The Savvy-Sally reason is that New correctly calls
Initialize.

*Exactly* the same reasons say you should use Dispose, not FreeMem.

About the pChar thing -- You almost never have to getMem on a pChar. In many
cases, you already have a string around with the correct contents, and all
you have to do is use pChar(myString). In other cases, either you don't, or
the pChar^ will be changed. Then you use a string again --

setLength(myString, sizeNeeded);
doMyThing(pChar(myString));
myString := pChar(myString); //to reset the length

Advantage is that you can then use string functions, and you have no worry
about deallocation.

PhR


0 new messages