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

D7 Compiler Bug

17 views
Skip to first unread message

VBDis

unread,
Sep 24, 2004, 5:51:50 AM9/24/04
to
After some problems with runtime errors I could find an bug in the D7 compiler,
possibly existing in previous versions as well. The bug is related to the
(deprecated) type Object, but it might apply also to type Class, without
alerting runtime errors but resulting in memory leaks (not yet tested).

In the following situation the compiler forgets to insert calls to
InitializeRecord and FinalizeRecords at the begin and end of subroutines:

1) The subroutine has local variables of type Object.
2) The type is derived from another Object type that contains dynamic fields
(AnsiString, dynamic arrays...).

Usually the compiler inserts calls to InitializeRecord at the begin of a
subroutine to initialize (zero) all references to dynamic elements (strings,
arrays...). This is true for variables of such types as well as for records
containing such elements. Arrays of datatypes with references to dynamic
elements also should be initialized properly, when e.g. SetLength is called for
such an array. In the described situation no such initialization is done, the
compiler seems to miss the existence of affected variables in base classes.
Then the references to e.g. strings are not cleared on entry of a subroutine,
and every attempt to reference the contents, or to change the length, of such
an string will most probably result in an AV and a corrupt heap.

In Class types the missing initialization has no fatal consequences, since
instances of such types are zeroed during construction. Nonetheless a missing
finalization on destruction of such objects can result in memory leaks.

Unfortunately the existence of calls to InitializeRecord etc. is not a proof
for correct code creation of the compiler, since these calls can be forced by
dynamic elements in the "top level" data type, or by the existence of local
variables of the affected types. It's also hard to determine which fields of a
datastructure are processed by InitializeRecord and FinalizeRecord, since the
offsets of the affected fields are passed to these subroutines in a hidden data
structure.

Sample code:

type
TBase = Object
public
s: string;
end;

TDerived = Object(TBase)
end;

procedure test;
var obj: TDerived; //okay for TBase!
begin
assert(obj.s = '', 'uninitialized dynamic variable');
end;

DoDi

Jamie

unread,
Sep 24, 2004, 4:27:02 PM9/24/04
to

VBDis wrote:

> Unfortunately the existence of calls to InitializeRecord etc. is not a proof
> for correct code creation of the compiler, since these calls can be forced by
> dynamic elements in the "top level" data type, or by the existence of local
> variables of the affected types. It's also hard to determine which fields of a
> datastructure are processed by InitializeRecord and FinalizeRecord, since the
> offsets of the affected fields are passed to these subroutines in a hidden data
> structure.
>
> Sample code:
>
> type
> TBase = Object
> public
> s: string;
> end;
>
> TDerived = Object(TBase)
> end;
>
> procedure test;
> var obj: TDerived; //okay for TBase!
> begin
> assert(obj.s = '', 'uninitialized dynamic variable');
> end;
>
> DoDi

the compiler is doing exactly what it should be doing, the string is
treated like any standard string that you may create
at the entry point of a block.
also take not that you are not using the dynamic type of objects which
would be the Tobject in this case, but the objects which came first.
i know its nice the delphi still supports these types and i am glad
that they do.
these types are static types in the way you did it.
you need to initiate the code your self.
its no different from the need to clear the string or define it to
something on the entry of a code block.
the years of TP i did i never saw any docs stating that these objects
were initiated automatically, you may also want to take note that this
kind of string your using is not the default 255 byte long string but a
dynamic string.
specify a size of 255 or less in the string instead and then you will
have the exact of TP.

Bjørge Sæther

unread,
Sep 24, 2004, 3:48:34 PM9/24/04
to
Jamie wrote:
> the years of TP i did i never saw any docs stating that these
> objects were initiated automatically, you may also want to take note
> that this kind of string your using is not the default 255 byte long
> string but a dynamic string.

In the TP days, no. But then there was no "magic strings" around. If you
actually end up with orphaned strings, I'd say that Delphi had not
implemented the 'object' type properly.

> specify a size of 255 or less in the string instead and then you
> will have the exact of TP.

I believe that his point isn't being compatible with TP, but still being
able to use the 'object' type. He's been using them in new Delphi projects,
AFAIR.

Whenever I see a long string type, I expect it to be properly finalized if I
don't pertform any hacks like FillChar(MyObj, SizeOf(MyObj));

--
Regards,

Bjørge Sæther
bjorge@haha_itte.no
-------------------------------------
I'll not spend any money on American Software products
until armed forces are out of Iraq.


Rob Kennedy

unread,
Sep 24, 2004, 5:56:00 PM9/24/04
to
Jamie wrote:

> VBDis wrote:
>> Sample code:
>>
>> type
>> TBase = Object
>> public
>> s: string;
>> end;
>>
>> TDerived = Object(TBase)
>> end;
>>
>> procedure test;
>> var obj: TDerived; //okay for TBase!

It's OK for TBase, but only due to chance. Insert a ShowMessage call to
display s's value, and the assertion should fail, even if ShowMessage
comes *after* Assert.

>> begin
>> assert(obj.s = '', 'uninitialized dynamic variable');
>> end;
>>
>> DoDi
>
> the compiler is doing exactly what it should be doing, the string is
> treated like any standard string that you may create
> at the entry point of a block.

No, it's not. The Assert function is failing, showing that the string is
not being treated correctly.

> also take not that you are not using the dynamic type of objects which
> would be the Tobject in this case, but the objects which came first.

Yes, I think Dodi realizes that already, given his message started out
"The bug is related to the (deprecated) type Object ... ."

> i know its nice the delphi still supports these types and i am glad
> that they do.

Delphi does not fully support old-style objects anymore. They work
sometimes, but not always. Borland knows this.

> you need to initiate the code your self.

That looks like the only way.

FillChar(obj, SizeOf(obj), 0);

And then remember to clear the object's fields before the function
returns, since I don't think that's happening properly, either.

> its no different from the need to clear the string or define it to
> something on the entry of a code block.

Strings don't need to be cleared. The compiler does it automatically,
mainly because it has to for the rest of the string code in the
procedure to operate properly. Declare a local string variable, or a
local record variable that contains a string, and that variable will get
initialized automatically upon entry to the procedure. Declare a local
old-style object, though, and apparently, its string fields won't always
be initialized.

> the years of TP i did i never saw any docs stating that these objects
> were initiated automatically, you may also want to take note that this
> kind of string your using is not the default 255 byte long string but a
> dynamic string.

Turbo Pascal documentation doesn't mention anything like that because
Turbo Pascal had no automatically allocated heap data types like
AnsiString that would need anything like that.

> specify a size of 255 or less in the string instead and then you will
> have the exact of TP.

Change the declaration of the s field to ShortString, and you'll still
get the same error.

I added a field to TDerived, and the compiler appears to initialize it
since the assertion line succeeds, but if I also use the field in normal
code, it's apparent that TDerived field isn't initialized, either.

--
Rob

Duncan Murdoch

unread,
Sep 25, 2004, 9:24:12 AM9/25/04
to
On 24 Sep 2004 09:51:50 GMT, vb...@aol.com (VBDis) wrote:

>After some problems with runtime errors I could find an bug in the D7 compiler,
>possibly existing in previous versions as well. The bug is related to the
>(deprecated) type Object, but it might apply also to type Class, without
>alerting runtime errors but resulting in memory leaks (not yet tested).

Your code would not be legal for Classes because of the lack of
initialization and the lack of static Class declarations, so I think
this only applies to Object.

But I'm unable to find any documentation about Object in my D5 help
system. Is it there in D7?

If Objects are undocumented, it's hard to claim you've got a bug.
Maybe the documentation would have said "don't do this" if it was
there.

>In the following situation the compiler forgets to insert calls to
>InitializeRecord and FinalizeRecords at the begin and end of subroutines:

Duncan Murdoch

Jamie

unread,
Sep 25, 2004, 3:02:08 PM9/25/04
to
objects are the static or dynamic version of OO
before the Classes came along..

Duncan Murdoch

unread,
Sep 25, 2004, 1:04:52 PM9/25/04
to
On Sat, 25 Sep 2004 12:02:08 -0700, Jamie
<jamie_5_not_vali...@charter.net> wrote:

>objects are the static or dynamic version of OO
>before the Classes came along..

I know that. But are they documented anywhere in D7?

Duncan Murdoch

Wolfgang Ehrhardt

unread,
Sep 25, 2004, 2:45:23 PM9/25/04
to
On Sat, 25 Sep 2004 09:24:12 -0400, Duncan Murdoch
<mur...@stats.uwo.ca> wrote:
[snip]

>
>But I'm unable to find any documentation about Object in my D5 help
>system. Is it there in D7?

In Delphi 5 Object Pascal Reference

"As an alternative to class types, you can declare object types
using the syntax

type objectTypeName = object (ancestorObjectType)

memberList
end;

where objectTypeName is any valid identifier,
(ancestorObjectType) is optional, and memberList declares
fields, methods, and properties. If (ancestorObjectType) is
omitted, then the new type has no ancestor. Object types
cannot have published members. Since object types do not
descend from TObject, they provide no built-in constructors,
destructors, or other methods. You can create instances of an
object type using the New procedure and destroy them with the
Dispose procedure, or you can simply declare variables of an
object type, just as you would with records.

Object types are supported for backward compatibility only.
Their use is not recommended."

Same for Delphi 6, nothing found in D7/German trial.

>
>If Objects are undocumented, it's hard to claim you've got a bug.
>Maybe the documentation would have said "don't do this" if it was
>there.
>
>>In the following situation the compiler forgets to insert calls to
>>InitializeRecord and FinalizeRecords at the begin and end of subroutines:
>
>Duncan Murdoch

--
In order to e-mail me a reply to this message, you will have
to remove PLEASE.REMOVE from the address shown in the header
or get it from http://home.netsurf.de/wolfgang.ehrhardt
(Free AES, CRC, Hash, and HMAC source for Pascal/Delphi)

Michael Brown

unread,
Sep 25, 2004, 9:54:33 PM9/25/04
to

Yup. Look under the index for the item "Object types":

"As an alternative to class types, you can declare object types using the
syntax

type objectTypeName = object (ancestorObjectType)
memberList
end;

where objectTypeName is any valid identifier, (ancestorObjectType) is
optional, and memberList declares fields, methods, and properties. If
(ancestorObjectType) is omitted, then the new type has no ancestor. Object
types cannot have published members.

Since object types do not descend from TObject, they provide no built-in
constructors, destructors, or other methods. You can create instances of an
object type using the New procedure and destroy them with the Dispose
procedure, or you can simply declare variables of an object type, just as
you would with records.

Object types are supported for backward compatibility only. Their use is not
recommended."

--
Michael Brown
www.emboss.co.nz : OOS/RSI software and more :)
Add michael@ to emboss.co.nz - My inbox is always open


Bjørge Sæther

unread,
Sep 26, 2004, 6:16:53 AM9/26/04
to
Michael Brown wrote:
> Object types are supported for backward compatibility only. Their use
> is not recommended."

The interesting thing about this statement is that there is no explaination
on *why* one should avoid them. I have always believed that you are
encouraged to use the new class-based objects because they are a) superior
regarding functionality, and b) the one using 'object' type objects will be
very lonely out there. Borland also won't offer them much thought.

If string fields are not properly handled in 'object' objects, it must be
concidered a bug. I believe they just forgot to check this, and that it
would take less than half an hour to fix it.

Jamie

unread,
Sep 26, 2004, 2:32:47 PM9/26/04
to
not that i know of, i have found allot of stuff that is
used in delphi starting from the days of TP that is
not talked about in the Delphi help.
a Turbo Pascal guide really helps on the
use of the OBJECTS type of OO.
a few have stated that Borland just has forgotten
to take it out., i for one think that they should
leave it in and document it. they don't have all the
options as the CLASS would have but do come into some
good use at times to avoid calling a create and releasing
the memory etc..
just look for Turbo PASCAL User Guides on the net.
there all over the place.
that is if your that interested.

VBDis

unread,
Sep 27, 2004, 2:37:56 AM9/27/04
to
Im Artikel <hex5d.11845$g%5.14...@news2.e.nsc.no>, "Bjørge Sæther"
<bjorge@hahaha_itte.no> schreibt:

>If string fields are not properly handled in 'object' objects, it must be
>concidered a bug. I believe they just forgot to check this, and that it
>would take less than half an hour to fix it.

The problem is related to inheritance. Dynamic members seem to be handled
properly in the Objects where they are defined, but not in derived Object
classes.

I used Object sometimes to construct "extendable" records, by using Object
inheritance. Unfortunately this approach also is affected by this bug :-(

DoDi

Jamie

unread,
Sep 27, 2004, 4:10:11 PM9/27/04
to
use shortstrings and get it over with.

VBDis

unread,
Sep 29, 2004, 9:42:00 PM9/29/04
to
Im Artikel <10lggsc...@corp.supernews.com>, Jamie
<jamie_5_not_vali...@charter.net> schreibt:

>use shortstrings and get it over with.

Strings and arrays of fixed size often are inappropriate, and most hard coded
limits turn out to be inappropriate sooner or later :-(

DoDi

Jamie

unread,
Sep 30, 2004, 3:57:12 PM9/30/04
to
not if your dealing with Records.
you really should be using shortstrings
for those events when you move data out to
memory or file in a while record.
i use short strings when ever possible for
speed and less dynamic heap fragmentation.
one's app could get a periodic memory
error if using lots of dynamic strings that
are getting reallocated all the time .
even though over all memory will report
being sufficient.
so it maybe a good thing to keep in mind.

Rob Kennedy

unread,
Sep 30, 2004, 1:36:20 PM9/30/04
to
Jamie wrote:
> not if your dealing with Records.

He's not dealing with records. He's dealing with old-style objects.

> you really should be using shortstrings
> for those events when you move data out to
> memory or file in a while record.

No one said anything about moving anything anywhere. And what's a while
record?

> i use short strings when ever possible for
> speed

You obviously don't use Delphi 5 or later.

> and less dynamic heap fragmentation.
> one's app could get a periodic memory
> error if using lots of dynamic strings that
> are getting reallocated all the time .
> even though over all memory will report
> being sufficient.
> so it maybe a good thing to keep in mind.

OK, let's forget about strings. In Dodi's original example, change the
object's string field to be a dynamic array, an interface reference, a
WideString, or a Variant, and then change the assertion test
accordingly. The assertion will fail. The problem is not limited to strings.

--
Rob

Bjørge Sæther

unread,
Sep 30, 2004, 4:48:30 PM9/30/04
to
Jamie wrote:
> not if your dealing with Records.
> you really should be using shortstrings
> for those events when you move data out to
> memory or file in a while record.
> i use short strings when ever possible for
> speed and less dynamic heap fragmentation.
> one's app could get a periodic memory
> error if using lots of dynamic strings that
> are getting reallocated all the time .
> even though over all memory will report
> being sufficient.
> so it maybe a good thing to keep in mind.

This is quite new to me, and I beluieve I have never experienced problems
with strings related to memory. Problems using long strings ? No, on the
contrary, I'd say. They're really quite effective, remember the "copy on
change" concept...and the fact that only pointers are passed around. It's
not really that different from short strings, except that they use the
amount of memory needed instead of an amount bein either too large or too
small. It *is* of course a point when dealing with really large sets of
data, and where string lengths are close to fixed.

Bjørge Sæther

unread,
Sep 30, 2004, 8:11:51 PM9/30/04
to
L D Blake wrote:

> On Thu, 30 Sep 2004 22:48:30 +0200, "Bjørge Sæther"
> <bjorge@hahaha_itte.no> wrote:
>
>> Jamie wrote:
>>> not if your dealing with Records.
>
>> This is quite new to me, and I beluieve I have never experienced
>> problems with strings related to memory. Problems using long strings
>> ? No, on the contrary, I'd say. They're really quite effective,
>> remember the "copy on change" concept...and the fact that only
>> pointers are passed around.
>
> Which is where problems can follow...
>
> If you had this record...
>
> MyFileData = record
> Name : ansistring;
> Age : word;
> Grade : byte;
> Salary: longword;
> end;
>
> And this file...
>
> var
> MyFile : file of MyFileData;

I haven't used the 'file of record' since sometime in '97...at the point
when I discovered the biggest problem: It's a maintenance nightmare. Even
worse than with database string fields.

> You'd run into trouble because when you wrote the record to disk you
> would be writing the *pointer* to the string, not the contents of the
> string. Files of type Record have to be built of fixed length
> records so the data positions in the file can be calculated... you
> can't do that with ansistrings.
>
> On the other hand...
>
> MyFileData = record
> Name : string[64];
> Age : word;
> Grade : byte;
> Salary: longword;
> end;
>
> ... will work correctly. Your name will be written to disk and every
> record is the same size so the data positions can be calculated and
> the information is reliably retrieved.

Once you have figured out how to write an application without the string
length limits, you won't go back unless forced to. The "forces" are usually
databases. No Delphi application of mine has limited string lengths. I also
had to create a ReadLn replacement to handle the fact that strings may
contain LineFeeds.

Short strings are gone never to reappear in my code. Experienced too many
cases like this: By the time you had "invented" some cpu/memory saving
technique and refined it into a generally useful algoritm, the PC industry
had regained your advantage by speeding up accordingly. A pity, indeed. I
have scrapped a lot of elegant, fast code over the years. The units from 7-8
years back I'm not even sure I still have backed up.
;-)

Message has been deleted

Bjørge Sæther

unread,
Sep 30, 2004, 10:03:14 PM9/30/04
to
L D Blake wrote:

> On Fri, 1 Oct 2004 02:11:51 +0200, "Bjørge Sæther"
> <bjorge@hahaha_itte.no> wrote:
>
>> Once you have figured out how to write an application without the
>> string length limits, you won't go back unless forced to. The
>> "forces" are usually databases. No Delphi application of mine has
>> limited string lengths. I also had to create a ReadLn replacement to
>> handle the fact that strings may contain LineFeeds.
>
> I write applications with long strings all the time. About the only
> place I use the short strings are in records that will end up on disk
> or in rare cases where I want the string defined in the static area
> of the program's memory.
>
> As is the case with all the functions and facilities of any
> programming language... each has their place and there's nothing
> wrong with using whatever you have at your disposal.

True enough. Only that I believe short strings wouldn't appear if it was the
other way around...that the dynamic strings were the norm. Who would want
those crippled strings ?

Maarten Wiltink

unread,
Oct 1, 2004, 4:21:31 AM10/1/04
to
"L D Blake" <n...@any.adr> wrote in message
news:5nbpl012b5iogo1jh...@4ax.com...
[...]

> I write applications with long strings all the time. About the only
> place I use the short strings are in records that will end up on disk
> or in rare cases where I want the string defined in the static area
> of the program's memory.

That sounds markedly different from the impression I've been getting
from you lately. Whenever records are mentioned, you jump in with an
adhortation to use short strings in them. That's fine if the record
is meant to live on disk, but not all records are. Most, I expect,
are born from the _design_ issue that a bunch of fields collectively
represent a single entity.

Groetjes,
Maarten Wiltink


VBDis

unread,
Oct 1, 2004, 4:39:49 AM10/1/04
to
Im Artikel <5v0pl01s4nq5h9vc7...@4ax.com>, L D Blake
<n...@any.adr> schreibt:

>You'd run into trouble because when you wrote the record to disk you would be
>writing the *pointer* to the string, not the contents of the string.

Such considerations already appeared in COBOL, with the USAGE COMPUTATIONAL vs.
USAGE DISPLAY. Depending on the usage one may have records with fixed-size
strings for file I/O, and have records, or better objects, with dynamic strings
in memory.

A friend of mine just had problems in sorting huge file lists, where the long
directory part in every file name eat up too much memory. The amount of memory
can be reduced significantly in this case, by splitting the file names into
directory and file parts, where the directory string can be reused for every
file in the same directory. The file structure required no change in this case,
every record was already stored in a variable-length line in a text file. I for
my part have already separated these parts in my own file list implementation,
resulting in distinct directory and file "records" in the text files. Then I
don't have to separate and merge the directory parts at all, but that solution
is not acceptable to my friend, at least not for now ;-)

DoDi

VBDis

unread,
Oct 1, 2004, 4:39:49 AM10/1/04
to
Im Artikel <2s2ughF...@uni-berlin.de>, Rob Kennedy <m...@privacy.net>
schreibt:

>> i use short strings when ever possible for
>> speed
>
>You obviously don't use Delphi 5 or later.

In D5 the string handling was changed to only use dynamic strings in
expressions, resulting in many implicit and often not necessary conversions.
This was one of the reasons why I continued to use D4, for the same reasons as
Jamie mentions. But in newer Delphi versions the handling of fixed size strings
was improved again, so that I don't feel a need for using fixed strings for
optimization reasons any more. Now I only still miss a substring feature, as
Java has, where substrings of another string are implemented as references into
the original string. But that's not a vital feature, in my parsers I've
implemented my own substring references into the memory resident source files.

DoDi

Message has been deleted
Message has been deleted
Message has been deleted

Rob Kennedy

unread,
Oct 1, 2004, 1:31:27 PM10/1/04
to
VBDis wrote:
> Now I only still miss a substring feature, as Java has, where
> substrings of another string are implemented as references into the
> original string.

An interesting idea, but probably a lot easier in Java since its strings
are immutable.

--
Rob

Martin Harvey (Demon account)

unread,
Oct 1, 2004, 5:00:14 PM10/1/04
to

I might further add that is realy depends on the encoding scheme: more
and more representations nowadays are (rightly IMHO)

1. storing full metadata in the data (ASN.1 and many TLV-like
representations) in a binary format.
2. If the format is textual, then it has a regular grammar (SGML
derivates, i.e. XML) and can be parsed.

On both cases, there's no case for fixed length strings, in fact the
former is especially well suited to Delphi long strings.

MH.

Jamie

unread,
Oct 2, 2004, 4:35:51 AM10/2/04
to

that could be done .
Var
OriginalString:String;
SubString:Pchar;
Begin
OrignalString := 'Something';
SubString := @OriginalString[an index ?];
--
that would work but i think that if the originalString
got increased in sized the pointer may change later on how ever,
using a shortString would solve that since it would always use the
same memory..
OriginalSting:String[255]; for example.

its just an idea . :) one of many..

Duncan Murdoch

unread,
Oct 2, 2004, 9:03:07 AM10/2/04
to
On Thu, 30 Sep 2004 18:14:36 -0400, L D Blake <n...@any.adr> wrote:

>On the other hand...
>
> MyFileData = record
> Name : string[64];
> Age : word;
> Grade : byte;
> Salary: longword;
> end;
>
>... will work correctly. Your name will be written to disk and every record
>is the same size so the data positions can be calculated and the information
>is reliably retrieved.

This is a bad idea for two reasons.

1. You have no guarantee that the next version of Delphi will be able
to read that record. You should have said "packed record". How much
filler is inserted between Name and Age? (I'd guess a byte, but it
might be 3...) How much between Grade and Salary?

2. If the string you put in Name is 10 characters long, you'll have
to explicitly clear the whole Name field first, or risk writing
passwords or other confidential information out in the slack part of
the string.

A better solution is to write a function that writes out just the
data. If you really want fixed length records, then have your write
function pad variable length fields with nulls, but it saves space to
write variable length records and maintain an index giving the offsets
into them.

Duncan Murdoch

Marco van de Voort

unread,
Oct 2, 2004, 1:04:22 PM10/2/04
to
On 2004-09-24, VBDis <vb...@aol.com> wrote:
> Sample code:
>
> type
> TBase = Object
> public
> s: string;
> end;
>
> TDerived = Object(TBase)
> end;
>
> procedure test;
> var obj: TDerived; //okay for TBase!
> begin
> assert(obj.s = '', 'uninitialized dynamic variable');
> end;

Initialising "obj" would be TP incompatible. So IMHO this is not a bug?

Marco van de Voort

unread,
Oct 2, 2004, 1:05:41 PM10/2/04
to
On 2004-09-26, Jamie <jamie_5_not_vali...@charter.net> wrote:
[about tobject TP object support]

> a few have stated that Borland just has forgotten
> to take it out.

The compiler changed totally from D1 to D2. So they explicitely had to
code it into D2. So it is there on purpose.

Rob Kennedy

unread,
Oct 2, 2004, 4:52:04 PM10/2/04
to
Marco van de Voort wrote:
> Initialising "obj" would be TP incompatible. So IMHO this is not a bug?

The mere act of having an AnsiString field would be TP incompatible. So
what? This isn't Turbo Pascal.

Try the following code, which uses an interface instead of a string to
demonstrate the same problem. I get an access violation on the second
line, as IntfCopy erroniously tries to call obj.stream._Release. If I
change obj's type to TBase, I don't get an exception.

type
TBase = object
public
stream: IUnknown;
end;

TDerived = object(TBase)
end;

procedure TForm1.FormClick(Sender: TObject);
var
obj: TDerived;
stream: TStream;
begin
stream := TMemoryStream.Create;
obj.stream := TStreamAdapter.Create(stream, soOwned);
end;


--
Rob

Maarten Wiltink

unread,
Oct 2, 2004, 2:48:17 PM10/2/04
to
"L D Blake" <n...@any.adr> wrote in message
news:m5pql05rq4s2n9cka...@4ax.com...
> On Fri, 01 Oct 2004 04:52:46 -0400, L D Blake <n...@any.adr> wrote:

>> No offense is intended but methinks you're making a bit much of this.
>
> Maarten,
> I'm sorry about this comment. It was the middle of the night, I was
> on a bad day. You didn't deserve that.

That's quite okay. I have a thick hide; you're entitled to your bad
days; last but not least you're not all wrong.

I am kicking your shins harder than anybody's. You haven't seen half
of the replies I started composing when you were, again!, telling
people to use Delphi to not a hundredth of its potential. I can live
with it when you don't want to be programming OO yourself, but I do
consider it misplaced to advocate that over a certain (quite limited)
extent. Rejecting the VCL altogether just isn't done. You see only
its flaws, when to most people it's just another layer, another
virtual machine, something that can be understood in its own right.
We don't have to understand it as an edifice in terms of the bricks
from which it is built. Seeing the trees is nice for later, but at
first, seeing the forest is enough.

Groetjes,
Maarten Wiltink


Message has been deleted
Message has been deleted

Maarten Wiltink

unread,
Oct 3, 2004, 4:03:12 PM10/3/04
to
"L D Blake" <n...@any.adr> wrote in message
news:dfb0m0ldtbt83o1d7...@4ax.com...
> On Sun, 3 Oct 2004 17:39:06 +0200, "Maarten Wiltink"
> <maa...@kittensandcats.net> wrote:
[...]
>> It also involved half a dozen custom-written components. OO is a
>> *great* way to keep things modular.
>
> Yes it is. But so are well structured units in standard Pascal.

True. Fifteen years ago, I wrote abstract datatypes in Turbo Pascal.
OO is a still-better mousetrap.


[...]
> Aside: One of my friends DJs wedding parties. We set him up with a
> MP3/MIDI rig using a soundblaster Extigy box on his laptop. You
> haven't lived until you've heard some of those songs through a set
> of beat up old Mission 7 speakers on the business end a 300 watt amp.

If it's worth playing, it's worth playing LOUDLY.


[...]
>> You write _quite_ small programs - not only in the sense that they
>> don't take up much disk space, but also, especially, in the sense
>> that they don't do much (and do it well, undoubtedly).
>
> [smile] I prefer to call them "function specific".

"Do one thing, and do it well" is not a criticism.


[...]
> But, you're right, the monster thread would most likely turn into a
> "Tastes Better -- Less Filling" kind of thing with people's pride
> coming to the fore and opinions flying about like snowflakes. Not
> exactly the most beneficial way to spend our time here...

Oh, you mean exactly like we had the first time you showed up? Not my
finest moments, those.


> Anyhow, I'm glad we have come closer to an understanding. Let me
> just leave you with a reminder that I don't dislike the VCL/RAD/OOP
> approach... I just figure it has it's place and time, as does the
> underlying Object Pascal.

You're not getting off that easily. You're throwing VCL, RAD, and
OOP all onto the same heap. But they're three quite distinct things.
RAD, as understood in relation to Delphi, is a visual design system.
It's not just about chucking things onto forms. Data modules are
_quite_ useful as abstractions and the Object Inspector is a brilliant
way of configuring things. Nevertheless, I could live without it for
small programs. For bigger programs, it's simply too convenient to
pass up.

The VCL is not only the system on top of which Delphi's RAD system
was built, it's also a library in its own right. Getting to understand
how it's organised was a great help to me in setting up my own programs.
I always had the example of the VCL, and there are a lot of good ideas
in it. It doesn't even matter (much) if they're all _really_ good, the
point is having ideas at all to build on. Building on what you already
have is always less work than starting from scratch, and what's more,
it's easier. I know people, professional programmers, whom I wouldn't
trust to set up an application. But they can add features to an existing
one without problems. And this is a stage that we all have to pass
through. The higher-level the layer we get to build on, the sooner we
make money for our bosses, simply because we can make bigger things
sooner.

And to forego object-orientation because you consider Delphi's RAD
system bloated (which it is; it just doesn't bother me) is totally
the wrong reaction. In university, the first programming class was
titled "Inleiding[0] Informatica", the second was "Datastructuren
& Algoritmen". This is a deep truth, that those two things are what
_all_ programming is about: data structures and algorithms. Much later,
I learned that there _was_ a third facet, and it was user interfacing.
But object-orientation is about how you deal with data structures and
algorithms much more than it is about GUIs. A program that has no
appreciable user interface can still benefit greatly from dealing
well with its data structures and its algorithms, and OO is simply
a very good way to do so. I don't think it's too much said that it's
the best way we know of... so far.

Still, it may be defensible to not design your program along object-
oriented lines. Like with every system, there is overhead and a
break-even point below which the product remains simpler without it.
But in my experience, almost as soon as there is a data _structure_,
it pays to do it OO.

Groetjes,
Maarten Wiltink

[0] Introduction


Message has been deleted

Marco van de Voort

unread,
Oct 4, 2004, 2:03:04 AM10/4/04
to
On 2004-10-02, Rob Kennedy <m...@privacy.net> wrote:
> Marco van de Voort wrote:
>> Initialising "obj" would be TP incompatible. So IMHO this is not a bug?
>
> The mere act of having an AnsiString field would be TP incompatible. So
> what? This isn't Turbo Pascal.

Yes, but as said, the TP object is legacy, and thus there is no need for
it to support such constructs.

I tried to look up in the BP language guide if initialisation is required
before using fields methods (since then the fields could be zeroed), however
it isn't. It is only required to be created and initialised for virtual
method use, there is nothing said about other cases.

I'm working under *nix here, and one could try to create and .init the object
and sees if it goes away (e.g. because the constructor zeroes).

Otherwise manual initialisation with e.g. pchar(y.field):=nil; is necessary,
one could move this to the .init method.


Maarten Wiltink

unread,
Oct 4, 2004, 2:06:04 AM10/4/04
to
"L D Blake" <n...@any.adr> wrote in message
news:vsp0m0daqof5j73hq...@4ax.com...
[...]
> I've never actually found myself comfortable with the high level
> abstractions and all that goes with them. I don't see Objects as
> most people do... data and code as a single functional entity.
> [...] I am, first, a repair tech.

And that's all the explaining you ever had to do. Let's all now
skip to living happily ever after.

Groetjes,
Maarten Wiltink


J French

unread,
Oct 4, 2004, 4:02:17 AM10/4/04
to
On Sun, 03 Oct 2004 17:21:46 -0400, L D Blake <n...@any.adr> wrote:

<snip>

>OO just doesn't fit my head very well... I just don't think that way.
>You do.. and that's just fine with me. Really, no grumbles on this end at
>all.

I'm not so sure about that, the chances are that you have been
applying OO principles for many years
- we certainly were - well before Windows

What is now called 'OO' is really a re-working and re-presentation of
a very old approach

Result := ProcA( Data, Param, Param )
Result := ProcB( Data, Param )

Where Data is just about completely unknown to anything outside the
procedures that use it, to anything else it is just a chunk of RAM

'New OO' is :-

Result := Data.ProcA( Param, Param )
Result := Data.ProcB( Param )

Which is more a change of 'syntax' than a revolutionary new concept

Note that the 'old method' was also a way of getting such wonders as
polymorphism and inheritance - not that we called them that.

The joke for me is that OO was explained to me by a young and trendy
programmer in 1987, and to do so he used examples of what we were
already doing.

Message has been deleted
Message has been deleted

Marco van de Voort

unread,
Oct 4, 2004, 2:11:26 PM10/4/04
to
On 2004-10-02, Maarten Wiltink <maa...@kittensandcats.net> wrote:
> days; last but not least you're not all wrong.
>
> I am kicking your shins harder than anybody's. You haven't seen half
> of the replies I started composing when you were, again!,

Ahum. I reserve myself that honour :-)

Message has been deleted

Bjørge Sæther

unread,
Oct 4, 2004, 8:18:21 PM10/4/04
to
J French wrote:
> On Sun, 03 Oct 2004 17:21:46 -0400, L D Blake <n...@any.adr> wrote:
>
> <snip>
>
>> OO just doesn't fit my head very well... I just don't think that way.
>> You do.. and that's just fine with me. Really, no grumbles on this
>> end at all.
>
> I'm not so sure about that, the chances are that you have been
> applying OO principles for many years
> - we certainly were - well before Windows
>
> What is now called 'OO' is really a re-working and re-presentation of
> a very old approach

Writing OO code in a language that doesn't support it does not seem like a
very good idea. Unless OOP is so outstanding that it would justify nearly
any kind of ugly hack ;-)

Noone is talking about a revolution here, only a *slight* improvement. The
magnitude could possibly resemble that of proper use of character case
compared to all upper- or lowercase. ;-)
No, seriously, it's simply a model of grouping things. I believe I'm still
evolving a sense of whether classes are "pure", in the meaning "whether
something belongs in class A or B". I often divide classes into
"type"-classes and "data" - classes, where the structures of the "types"
control the instantiation of the "data" - classes. I just cannot see how I
could have myself trained this way if writing non-OO code. It's like when
constructing a house: "What elements do I connect, and what leans on what ?"
While I do write non-OO code all the time, there is typically a movement
towards objects as the project grows. The downside is of course that the
decision on creating a class model may involve quite some work. But again
and again I conclude that the error was writing all of that spaghetti
instead of doing it properly from the beginning.
--
Regards,

Bjørge Sæther
bjorge@haha_itte.no
-------------------------------------
I'll not spend any money on American Software products
until armed forces are out of Iraq.

J French

unread,
Oct 5, 2004, 3:08:23 AM10/5/04
to
On Tue, 5 Oct 2004 02:18:21 +0200, "Bjørge Sæther"
<bjorge@hahaha_itte.no> wrote:

>J French wrote:
>> On Sun, 03 Oct 2004 17:21:46 -0400, L D Blake <n...@any.adr> wrote:
>>
>> <snip>
>>
>>> OO just doesn't fit my head very well... I just don't think that way.
>>> You do.. and that's just fine with me. Really, no grumbles on this
>>> end at all.
>>
>> I'm not so sure about that, the chances are that you have been
>> applying OO principles for many years
>> - we certainly were - well before Windows
>>
>> What is now called 'OO' is really a re-working and re-presentation of
>> a very old approach

>Writing OO code in a language that doesn't support it does not seem like a
>very good idea. Unless OOP is so outstanding that it would justify nearly
>any kind of ugly hack ;-)

I can't agree with you here
We found that the methods we used vastly simplified applications,
encapsulated functionality and gave us 'hidden flexibility'

There were no real 'hacks' or code contortions, it was just the
logical way to design the code.

>Noone is talking about a revolution here, only a *slight* improvement. The
>magnitude could possibly resemble that of proper use of character case
>compared to all upper- or lowercase. ;-)
>No, seriously, it's simply a model of grouping things. I believe I'm still
>evolving a sense of whether classes are "pure", in the meaning "whether
>something belongs in class A or B". I often divide classes into
>"type"-classes and "data" - classes, where the structures of the "types"
>control the instantiation of the "data" - classes. I just cannot see how I
>could have myself trained this way if writing non-OO code. It's like when
>constructing a house: "What elements do I connect, and what leans on what ?"

Yes, that makes sense

>While I do write non-OO code all the time, there is typically a movement
>towards objects as the project grows. The downside is of course that the
>decision on creating a class model may involve quite some work. But again
>and again I conclude that the error was writing all of that spaghetti
>instead of doing it properly from the beginning.

Often one starts something as a single instance, and then realizes
that it would make more sense wrapping it up and being able to
maintain multiple instances.

Also, however much one plans, one often 'discovers' something while
coding which (should) necessitate a partial re-write.

Also, one of the advantages I find from OO as it is now implemented,
is that one can 'hide' code and data away in the certainty that one
will not be tempted to re-use it 'a la bolognese'

VBDis

unread,
Oct 5, 2004, 4:51:05 PM10/5/04
to
Im Artikel <slrncltnv5....@turtle.stack.nl>, Marco van de Voort
<mar...@stack.nl> schreibt:

>[about tobject TP object support]
>
>> a few have stated that Borland just has forgotten
>> to take it out.
>
>The compiler changed totally from D1 to D2. So they explicitely had to
>code it into D2. So it is there on purpose.

The documentation says that the Object type is supported for compatibility
reasons. This might mean that dynamic types (AnsiString...) cannot occur in
legacy (TP...) code and consequently these new types must not be supported in
Object.

But it's a half-hearted policy to support Object even in D7 without mentioning
or correcting hard limits in the implementation and use of that data type. The
Delphi compiler IMO is very reliable, so it's very strange to learn that there
exist situations where the compiler definitely produces broken code :-(

DoDi

VBDis

unread,
Oct 5, 2004, 4:51:05 PM10/5/04
to
Im Artikel <4160fce...@news.btclick.com>, ere...@nowhere.com (J French)
schreibt:

>'New OO' is :-
>
>Result := Data.ProcA( Param, Param )
>Result := Data.ProcB( Param )
>
>Which is more a change of 'syntax' than a revolutionary new concept

The mind shift starts with the syntax change, but afterwards one will find many
more useful things with true OOP.

>Note that the 'old method' was also a way of getting such wonders as
>polymorphism and inheritance - not that we called them that.

You missed virtual methods, which together with inheritance and polymorphism
are hard until impossible to implement in non-OO languages. I wonder how you
will implement polymorphism and inheritance without error prone hacks (explicit
uncheckable typecasts...), when no extendable data type exists in a language.

I remember an example (OpenXP), where the menu handler was a single huge
procedure of > 100,000 lines. It was almost impossible to restructure that
procedure, since in no place it was clear what data a record really contained.
The author had released his TP code into the public domain, because he found
the code impossible to maintain any more. Even if that author wrote pretty
structured code allover, without OO and true polymorphism he ended up with
spaghetti soup :-(

DoDi

J French

unread,
Oct 6, 2004, 3:09:32 AM10/6/04
to
On 05 Oct 2004 20:51:05 GMT, vb...@aol.com (VBDis) wrote:

>Im Artikel <4160fce...@news.btclick.com>, ere...@nowhere.com (J French)
>schreibt:
>
>>'New OO' is :-
>>
>>Result := Data.ProcA( Param, Param )
>>Result := Data.ProcB( Param )
>>
>>Which is more a change of 'syntax' than a revolutionary new concept

>The mind shift starts with the syntax change, but afterwards one will find many
>more useful things with true OOP.

True - New style is easier

>>Note that the 'old method' was also a way of getting such wonders as
>>polymorphism and inheritance - not that we called them that.

>You missed virtual methods, which together with inheritance and polymorphism
>are hard until impossible to implement in non-OO languages. I wonder how you
>will implement polymorphism and inheritance without error prone hacks (explicit
>uncheckable typecasts...), when no extendable data type exists in a language.

Not necessarily, the Data contains flags that indicates its own
'version'
- I believe you use a similar method when saving things to streams

>I remember an example (OpenXP), where the menu handler was a single huge
>procedure of > 100,000 lines. It was almost impossible to restructure that
>procedure, since in no place it was clear what data a record really contained.
>The author had released his TP code into the public domain, because he found
>the code impossible to maintain any more. Even if that author wrote pretty
>structured code allover, without OO and true polymorphism he ended up with
>spaghetti soup :-(

Realistically, what I am saying is that OO principles are not new
- it is just that they are more conveniently implemented in languages
like Delphi

Marco van de Voort

unread,
Oct 6, 2004, 3:32:11 AM10/6/04
to
On 2004-10-05, VBDis <vb...@aol.com> wrote:
>>> to take it out.
>>
>>The compiler changed totally from D1 to D2. So they explicitely had to
>>code it into D2. So it is there on purpose.
>
> The documentation says that the Object type is supported for compatibility
> reasons. This might mean that dynamic types (AnsiString...) cannot occur in
> legacy (TP...) code and consequently these new types must not be supported in
> Object.

Yes, that is my opinion (and expectation) too. Even if it was supported, I
only expect it to work when constructed properly. Otherwise it would become
an automatic object.

> But it's a half-hearted policy to support Object even in D7 without
> mentioning or correcting hard limits in the implementation and use of that
> data type. The Delphi compiler IMO is very reliable, so it's very strange
> to learn that there exist situations where the compiler definitely
> produces broken code :-(

IMHO this is a documentation fault, and the compiler is fine. FPC
independantly has the same behaviour.

It's a pity that it hasn't been released to PD (or MPL) yet, but I still
want to try to get Turbo Vision compiling under Delphi one day. That would
really stress the object mechanism.

VBDis

unread,
Oct 6, 2004, 7:04:43 AM10/6/04
to
Im Artikel <4163980b...@news.btclick.com>, ere...@nowhere.com (J French)
schreibt:

>Realistically, what I am saying is that OO principles are not new


>- it is just that they are more conveniently implemented in languages
>like Delphi

A long time ago somebody said that a language should not only offer some
feature, but instead it also should encourage to use that feature.

IMO this is the key point in discussions about "why Delphi", "why OO" - it's
not the existance of some feature, instead it's the advantage resulting from
the use of the features.

DoDi

J French

unread,
Oct 6, 2004, 9:43:09 AM10/6/04
to

IMO - treat it as a Smorgasbord

Message has been deleted
Message has been deleted

VBDis

unread,
Oct 7, 2004, 6:59:19 AM10/7/04
to
Im Artikel <slrncm77rr....@turtle.stack.nl>, Marco van de Voort
<mar...@stack.nl> schreibt:

>> But it's a half-hearted policy to support Object even in D7 without


>> mentioning or correcting hard limits in the implementation and use of that
>> data type. The Delphi compiler IMO is very reliable, so it's very strange
>> to learn that there exist situations where the compiler definitely
>> produces broken code :-(
>
>IMHO this is a documentation fault, and the compiler is fine. FPC
>independantly has the same behaviour.

A proper implementation only would require an "legacy" switch, or another mode
in FPC, that enables Object and disables AnsiString and other unsupported
extensions in that context. Then the compiler can reject unhandled situations,
instead of silently producing buggy code.

>It's a pity that it hasn't been released to PD (or MPL) yet, but I still
>want to try to get Turbo Vision compiling under Delphi one day. That would
>really stress the object mechanism.

During my first steps with BC3 I studied the OWL and found it not very well
designed, with regards to customization. GUI elements deserve a very careful
design, that does not hard code a specific behaviour of sub-components into the
base classes. In my experiments it was impossible to preserve the current
position in lists when scrolling up and down by pages - the current position
frequently changed by arbitrary numbers of lines, depending on the situation.
Perhaps newer versions have a better design?

DoDi

Marco van de Voort

unread,
Oct 7, 2004, 8:17:38 AM10/7/04
to
On 2004-10-07, VBDis <vb...@aol.com> wrote:
>>> data type. The Delphi compiler IMO is very reliable, so it's very strange
>>> to learn that there exist situations where the compiler definitely
>>> produces broken code :-(
>>
>>IMHO this is a documentation fault, and the compiler is fine. FPC
>>independantly has the same behaviour.
>
> A proper implementation only would require an "legacy" switch, or another
> mode in FPC, that enables Object and disables AnsiString and other
> unsupported extensions in that context.

IMHO this is a kludge. If you want static objects that badly, define a new
object system for it, don't try to retrofit legacy systems.

> Then the compiler can reject unhandled situations, instead of silently
> producing buggy code.

There is no official code that does this. Moreover, IMHO the code was doubly
broken, since an object was accessed before creation.

>>It's a pity that it hasn't been released to PD (or MPL) yet, but I still
>>want to try to get Turbo Vision compiling under Delphi one day. That would
>>really stress the object mechanism.
>
> During my first steps with BC3 I studied the OWL and found it not very well
> designed, with regards to customization. GUI elements deserve a very careful
> design, that does not hard code a specific behaviour of sub-components into the
> base classes. In my experiments it was impossible to preserve the current
> position in lists when scrolling up and down by pages - the current position
> frequently changed by arbitrary numbers of lines, depending on the situation.
> Perhaps newer versions have a better design?

I never used OWL or any other Borland Windows compiler before D4. Only TV,
LCL and a bit of VCL.

TV was reasonably well designed IIRC, except for some 16-bitisms that are
easily fixed. Most problems stem from limitations in the TP object model,
not from TV.

Catherine Rees Lay

unread,
Oct 6, 2004, 9:31:08 AM10/6/04
to
In article <p07ql0lo3qi1h0h85...@4ax.com>, L D Blake
<n...@any.adr> writes
>On 01 Oct 2004 08:39:49 GMT, vb...@aol.com (VBDis) wrote:
>
>>Now I only still miss a substring feature, as
>>Java has, where substrings of another string are implemented as
>>references into
>>the original string. But that's not a vital feature, in my parsers I've
>>implemented my own substring references into the memory resident source files.
>
>Syntax wishlist, Item 42...
>
> SubStr := MainStr[32..126];
> SubStr := MainStr[X..Y];
>
Oh, I agree so much...

FORTRAN 77 had this, for goodness sake. It's incredibly simple, obvious
and useful. I miss it so much when I'm working in Delphi. I catch myself
writing it all the time, and then can't believe it doesn't work.

Catherine.
>
>-----
>Laura
>
>(http://www.start.ca/users/ldblake)

--
Catherine Rees Lay
To email me, use my first name in front of the "at".

VBDis

unread,
Oct 12, 2004, 4:38:48 AM10/12/04
to
Im Artikel <4163980b...@news.btclick.com>, ere...@nowhere.com (J French)
schreibt:

>Realistically, what I am saying is that OO principles are not new


>- it is just that they are more conveniently implemented in languages
>like Delphi

A long time ago somebody said that a language should not only offer some


feature, but instead it also should encourage to use that feature.

IMO this is the key point in discussions about "why Delphi", "why OO" - it's
not the existance of some feature, instead it's the advantage resulting from
the use of the features.

DoDi

0 new messages