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

Re: Exception Handling...

158 views
Skip to first unread message
Message has been deleted

Dodgy

unread,
Jun 22, 2004, 8:45:36 AM6/22/04
to
On Tue, 22 Jun 2004 02:57:37 -0400, nob...@noplace.not waffled on
about something:

>Ok guys I've got a dandy question for you...
>
>I'm working on a couple of console based custom diagnostic tools that have
>to fit on floppies... So program size is a big issue...
>
>I've been going through parts of the Delphi 7 RTL fixing a couple of minor
>issues and generally seeing what can be done to improve parts of the code.
>For example, I've knocked their Memory Manager down from nearly 40k to less
>than 4k and gained some speed in the process. A few other fixups like
>creating a prototype for "initexceptions" and "doneexceptions" in the
>interface of the SysUtils unit have come in handy as I can turn exception
>handling off and on pretty much at will (yeah, I know, bad practice but
>still necessary on occasions).
>
>But I'm stuck on one thing...
>
>The exception handling code, scattered between the System and SysUtils units
>reads like alphabet soup. Really, it's more tangled up than their memory
>manager... What I want to do is get the "Try Except" and "Try Finally"
>functions working without the bulky Tobject references. Ideally I would use
>the WinApi's GetExceptionCode etc. to access the exception information. By
>my best determinations this should bring the minimum EXE size down to about
>10k, if I can do it...
>
>With the new memory manager this...
>
> program test;
> uses
> sysutils;
> begin
> writeln('hello');
> end.
>
>Produces an exe of about 33k.
>
>Commenting out the "initexceptions" call from the initialization of SysUtils
>reduces the size to about 16k. (but, of course, try/except does nothing
>when you do that)
>
>
>Anyone care to lend a hand?
>
>I'll be happy to make the modified RTL units available when the job is
>done...
>
>-----
>Laura

Taking a slight step back the first thing that comes to mind is have
you thought about using an exe compressor? It would save you a hell of
a lot of work and would probably get the exe size lower than you could
ever manage with just code/library streamlining.

http://upx.sourceforge.net/
http://www.un4seen.com/petite/

Dodgy.
--
MUSHROOMS ARE THE OPIATE OF THE MOOSES

Bruce Roberts

unread,
Jun 22, 2004, 8:54:15 AM6/22/04
to

<nob...@noplace.not> wrote in message
news:84lfd0tbc6eln8rdn...@4ax.com...

> I'm working on a couple of console based custom diagnostic tools that have
> to fit on floppies... So program size is a big issue...

You might want to check out a web site (http://www.bonanzas.rinet.ru/)
referenced in the Small Executables thread which ran most of last week. I
suspect that you will find the site most helpful.


Message has been deleted
Message has been deleted

Dodgy

unread,
Jun 23, 2004, 5:48:18 AM6/23/04
to
On Tue, 22 Jun 2004 17:59:01 -0400, nob...@noplace.not waffled on
about something:

>On Tue, 22 Jun 2004 13:45:36 +0100, Dodgy <Do...@earth.planet.universe>
>wrote:


>
>>Taking a slight step back the first thing that comes to mind is have
>>you thought about using an exe compressor? It would save you a hell of
>>a lot of work and would probably get the exe size lower than you could
>>ever manage with just code/library streamlining.
>

>Yes, the thought occurred. But still, having been through their memory
>manager and bringing it down from 1500 lines to 80 I now find myself quite
>locked into the idea of de-bloating the whole thing.

Ah, you've found your mission...

DelphiLite :-)

>I've even considered starting from zilch and reconstructing the whole
>system, sysutils, sysinit section of the RTL. Picture two units...
>
>System; with reserved word support, memory and exception management, DLL and
>Units support, etc. just enough code to get things up and running, really.
>
>Syntax; with all the combined niceties from the current system and sysutils
>units. Such a split would let people maintain core functionality through
>the System unit even while substituting different syntax units to
>essentially re-write the language.
>
>One of the big reasons I wanted to redo the Exception Handling is that it's
>OS proximate and it's using objects and classes, which I'm not entirely
>comfortable with. When you get right down to core functionality, I'd much
>rather work procedurally than by objects. Most often the result is smaller
>and faster code.

Does sound nice, but a hell of a lot of work, but hey, if it keeps you
happy and the boss pays for the time you're taking, who am I to
complain!

Message has been deleted

Bruce Roberts

unread,
Jun 23, 2004, 10:27:38 AM6/23/04
to

<nob...@noplace.not> wrote in message
news:42ahd0lt37jp73lt2...@4ax.com...

> One of the big reasons I wanted to redo the Exception Handling is that
it's
> OS proximate and it's using objects and classes, which I'm not entirely
> comfortable with. When you get right down to core functionality, I'd much
> rather work procedurally than by objects. Most often the result is
smaller
> and faster code.

You are making a generalization that doesn't hold up very well. MS is often
accused of producing bloaty (is that a word?) code yet they didn't start
using pure OO until relatively recently. OS360 and PL/1 are great examples
of bloaty code but both of them were produced well before objects entered
the CS lexicon. And COBOL sure didn't contribute very much to smaller and
faster code, but its never seen an object.

Smaller and faster code is produced when one chooses good algorithms,
implements them well, and in isolation. IOW as long as one can write an
entirely new program to address a very narrow and specific problem with no
backward or forward compatibility constraints.

OO offers so many design, build, and maintenance benefits that to ignore it
because of comfort level begs the question of masochism.


Message has been deleted

David Reeve

unread,
Jun 23, 2004, 10:46:19 PM6/23/04
to
<nob...@noplace.not> wrote in message
news:shoid05cca8c0s3nr...@4ax.com...
[snip]
> Not to worry. I've got the time to put into it, that's why they make
> evenings, I believe. Seriously though, it sounds like something I would
> like to do, but there are still a few intricacies I don't understand.
>
> Frankly, the exception handling is giving me fits. I'm just not getting
my
> head around it. I really do want to get the exception handling going so
that
> Try/finally and try/except work without sysutils, objects or any of the
> related overhead... just a few lines of code to transfer program control,
> let me deal with the exception and get back to the main flow of things.
>
> The thing I'm having trouble finding is any detail on how an exception
> thrown by windows triggers a reaction in Delphi. At the moment it looks
> like a "you can't get here from there" kind of thing... Where's the entry
> point?
>

I'm interested in this simply from the point of view of understanding, but
it does have some bearing on writing DLLs and multithreaded stuff. I made
some progress a couple of years ago, but haven't had the time or the
enthusiasm since then to proceed further. If you post up what you find out,
how you think it works etc, I for one would be interested in having a look.
However, I don't have more than a few hours a day free, so don't expect
instant answers.

Dave


Message has been deleted

David Reeve

unread,
Jun 24, 2004, 10:32:34 PM6/24/04
to
<nob...@noplace.not> wrote in message
news:s6mkd0ha6ig4jlg42...@4ax.com...
> On Thu, 24 Jun 2004 02:46:19 GMT, "David Reeve" <dree...@big-pond.net.au>
> wrote:
>
[snip]

> One would expect Delphi to track the beginning and end of "Try" blocks and
> refer any exception occurring within it's boundaries to a specific
> subroutine that gets you into the "Except" block or the "Finally" block of
> the protected code. But these entry points are quite elusive. Also you
> would hope to find an external entry point that would be called by windows
> when an exception occurs; also elusive.
>

A couple of points that you might or might not know, which also might or
might not be correct, but is based on what I have gleaned to date. I'll do
some more digging around on the weekend.

a) since D2, Delphi uses the SEH system of the W32 OS
b) most of the exception behaviour is occuring in the OS and you won't find
the code in Delphi

Forget, for the moment, exceptions raised in delphi code using the raise key
word. Exceptions will be generated at the machine level by code running in
user mode, and these will be handled firstly by the OS. The machine state is
grabbed into the context record so that recovery is possible should an
exception handler be located. The OS then unwinds the stack frame of the
thread which executed the errant code, procedure call by procedure call as
it looks for what??........ Some sort of datastructure embedded in the stack
frame I guess, which indicates the preceding procedure in the call sequence
was bracketed by a try...except block, and that it should handled by the
code at such and such an address. Note that no Delphi code need be run until
the exception code is entered.

What you have to work out is what Delphi does when it compiles a
try...except block, and the best way to do this is to compile a simple
example with and without the block and step the code at the assembler level.

Dave


Message has been deleted
Message has been deleted

VBDis

unread,
Jun 26, 2004, 10:11:25 AM6/26/04
to
Im Artikel <69MCc.63427$sj4....@news-server.bigpond.net.au>, "David Reeve"
<dree...@big-pond.net.au> schreibt:

>The OS then unwinds the stack frame of the
>thread which executed the errant code, procedure call by procedure call as
>it looks for what??........

Isn't the FS segment register used for exception handling? I vaguely remember
its use in Microsoft compilers...

DoDi

David Reeve

unread,
Jun 26, 2004, 10:28:02 AM6/26/04
to
<nob...@noplace.not> wrote in message
news:rr5od0l0po3v1inhs...@4ax.com...

> On Fri, 25 Jun 2004 02:32:34 GMT, "David Reeve" <dree...@big-pond.net.au>
> wrote:
>
> >A couple of points that you might or might not know, which also might or
> >might not be correct, but is based on what I have gleaned to date. I'll
do
> >some more digging around on the weekend.
>
> Hi David,
> I went out looking last night and found a very interesting article on the
> intricacies of SEH in C++ and at the OS level. Thought you might like to
> get a look at it...
>
> http://www.microsoft.com/msj/0197/Exception/Exception.aspx
>
> Prints out to 24 pages but it seems very thorough.
>
> It's going to take me more than one read to absorb it though...
>

Thanks for the link Laura. You're right, that one will take a bit of
digesting. I tried to get an overview of what Delphi does when it compiles
the try..except block. The following are observations and should be taken as
an innocent's view of something rather complicated, and very much work in
progress.

procedure TForm1.Button1Click(Sender: TObject);
begin
try
y := x/0;
except
HandleZeroDivide;
end;
end;

procedure TForm1.HandleZeroDivide;
begin
y := 1.0;
end;

Firstly the above code traps out the divide by zero as expected..... a good
start. Secondly, I am stepping the assembler to follow what happens.

The try key word results in the current stack frame base, the address of
HandleZeroDivide and some other stuff I don't understand being pushed on
stack. This is all that happens. No calls are made to the OS or Delphi RTL.

The except keyword inserts a jump to the normal cleanup and exit part of the
procedure. Immediately following this jump, there is inserted a jump to
NotifyAnyException which looks like being in the Delphi RTL, then follows
the jump to HandleZeroDivide, followed by the normal exit code.

When I say try inserts this and except that, obviously the compiler is
working with the complete construct and doesn't allow partial coding..... as
I said, thus far I'm taking a rather simple view of matters. So what happens
when this code is stepped. Well everything runs in line as per the source
until the wait instruction to the FPU executes and then you suddenly appear
in the KiUserExceptionDispatcher function of ntdll, presumably the first
port of call in the OS SEH mechanism. Maybe four or five calls to other
parts of this dll (not exported functions), and you magically land back at
the jump to HandleAnyException in the compiled source.
HandleAnyException after jumping around the Delphi RTL and back into ntdll,
finally calls the exception handler, calls DoneExcept in the RTL and makes
the standard exit.

What does HandleAnyException has the following call sequence, all apparently
in the Delphi RTL...
FPUInit
NotifyNonDelphiException
RTLUnwind .... note this function is in ntdll
GetTls
NotifyAnyExcept

The above may give some clues as to how the various fragments of code in
sysUtils etc fit together. But I can see things getting an awful lot more
complicated before getting better :-)

Dave

Message has been deleted
Message has been deleted

Martin Harvey (Demon Account)

unread,
Jun 26, 2004, 6:16:26 PM6/26/04
to

Note that I haven't had time to read the article, and I haven't got
access to system or sysyutils.pas, so all my mouthing off is simply my
recollection, tempered with a bit of guesswork.

>NotifyAnyException is in System.pas ...
>But why would it go there if the registration on the stack points to your
>handler function?

There's a difference between Delphi language exceptions and OS
exceptions, and at some point, the delphi RTL has to make a mapping
from the latter to the former. Perhaps this happens here? (Aint there
something called "GetExceptionObject" or something similar somewhere?)

>Yeah, it does look that way doesn't it?

Oh balls - you're not gonna make me read it, and then explain it to
you, are you??? Next thing, you'll be asking me to do it without the
source for system / sysutils, and just step thru the assembly instead
;-)

GRRR.

MH.

Message has been deleted

pr

unread,
Jun 27, 2004, 1:40:12 AM6/27/04
to

<nob...@noplace.not> wrote in message
news:84lfd0tbc6eln8rdn...@4ax.com...
: Ok guys I've got a dandy question for you...
:
: I'm working on a couple of console based custom diagnostic tools that have

: to fit on floppies... So program size is a big issue...

Just put the programs on a CD. Many notebooks do
not even have a stiffy drive anymore and it has to be
bought as an accessory. Over the last two years
I have not seen a single new extra part, printer ports,
display cards, etc. that came with stiffies or floppies.
Many networked desktop computers have no stiffies
anymore.
For what market are you writing? The number of people
who still use stiffies will be ever decreasing.
I would consider your attempts to replace the exception
handling (of all things!?) a total waste of time.

PR

Message has been deleted

Terry Russell

unread,
Jun 27, 2004, 3:24:44 AM6/27/04
to

<nob...@noplace.not> wrote in message
news:41psd0hk5c2qngvqk...@4ax.com...

> On Sun, 27 Jun 2004 07:40:12 +0200, "pr" <sh...@netactive.co.za> wrote:
>
> >Just put the programs on a CD.
>
> I cannot. I already explained that one of the requirements was that they
> all fit on one floppy.
>
> Here nor there, anyway as I delivered the software Friday.

>
>
> >For what market are you writing? The number of people
> >who still use stiffies will be ever decreasing.
> >I would consider your attempts to replace the exception
> >handling (of all things!?) a total waste of time.
>
> No offense my friend, but nothing that makes my code smaller faster or
more
> stable is ever a waste of time.

At 18 you have 1 billion seconds of working life left.
At average wages one second of your time is now worth
4 megabytes of permanent storage
2 Gigaflop
All code is a waste of time, unless this is what you really _want_ to do
as opposed to what you want the code to do.

Message has been deleted

Terry Russell

unread,
Jun 27, 2004, 4:48:31 AM6/27/04
to
<nob...@noplace.not> wrote in message
news:nuvsd09mjnvfnr96f...@4ax.com...

> On Sun, 27 Jun 2004 16:54:44 +0930, "Terry Russell"
> <troc...@oRpEtMuOsVnEet.com.au> wrote:
>
> >All code is a waste of time,
>
> Considered a new line of work?

If will gladly swap one gigabyte of storage today for anyone who
can give me back 5 minutes last Tuesday.

Elegant, compact and bugfree,
it means nothing to me
if it doesn't have EIP

;-)

J French

unread,
Jun 27, 2004, 6:15:57 AM6/27/04
to
On Sun, 27 Jun 2004 18:18:31 +0930, "Terry Russell"
<troc...@oRpEtMuOsVnEet.com.au> wrote:

><nob...@noplace.not> wrote in message
>news:nuvsd09mjnvfnr96f...@4ax.com...
>> On Sun, 27 Jun 2004 16:54:44 +0930, "Terry Russell"
>> <troc...@oRpEtMuOsVnEet.com.au> wrote:
>>
>> >All code is a waste of time,
>>
>> Considered a new line of work?
>
>If will gladly swap one gigabyte of storage today for anyone who
>can give me back 5 minutes last Tuesday.
>
>Elegant, compact and bugfree,
>it means nothing to me
>if it doesn't have EIP

What is 'EIP' ?

Martin Harvey (Demon Account)

unread,
Jun 27, 2004, 9:31:31 AM6/27/04
to
On Sun, 27 Jun 2004 18:18:31 +0930, "Terry Russell"
<troc...@oRpEtMuOsVnEet.com.au> wrote:

>If will gladly swap one gigabyte of storage today for anyone who
>can give me back 5 minutes last Tuesday.

A man after my own heart. I can think of moments in my life where for
the want of another 5 minutes of time I would happily have given
thousands of pounds.

(And NO - they're not those sorts of moments - just decision moments
where given another 5 minutes, I would have done things differently
and my life would have massively changed as a result).

MH.

Martin Harvey (Demon Account)

unread,
Jun 27, 2004, 9:31:59 AM6/27/04
to
On Sun, 27 Jun 2004 10:15:57 +0000 (UTC), ere...@nowhere.com (J
French) wrote:

>What is 'EIP' ?

Instruction pointer.

MH.

J French

unread,
Jun 27, 2004, 10:50:28 AM6/27/04
to

EIP goddam it

But in this context :

Elegant, compact and bugfree,
it means nothing to me
if it doesn't have EIP

What does Terry mean - is he saying 32bit Ok, 16 bit not ok ?

I understand the hardware software argument, as a canny old coder told
me 20 years ago
'why take risk saving the client disk space
- if they get a bigger disk they will see is as an asset
- and brag about it to their friends'

Surely, the maxim is careful and re-useable code

David Reeve

unread,
Jun 27, 2004, 11:22:24 AM6/27/04
to
<nob...@noplace.not> wrote in message
news:5ggrd05qg7gp4aib7...@4ax.com...
[snip]

> >The try key word results in the current stack frame base, the address of
> >HandleZeroDivide and some other stuff I don't understand being pushed on
> >stack. This is all that happens. No calls are made to the OS or Delphi
RTL.
>
> Based on the article...that might actually make sense... It's registering
> an exception callback... Part of the linked list described in the article
>
> If my reading of Delphi's code is right they also push several dwords of
> private data on top of the Exception Registration... for what reason I
don't
> yet know. If you look in system.pas in the lines 1700 -- 1775 area you
will
> find a number of structures to do with exceptions... can you by chance
tell
> if it's one of these?
>

Hmmm... I'm on D5 and 1700ish contains all sorts of string manupulation
primitives. Do you have type name I can search on?

In any event, things are starting to make sense. Indeed this is a SEH
registration being dropped on the stack. Dodi's suggestion, elsewhere in
this thread, that the FS register is used, and your follow-up, points the
way. The try keyword results in the following.....

xor eax,eax; // clear eax
push ebp; // push frame base ptr ....... this must be an RTL
thing
push @HandleZeroDivide; // loads address of exception handler
push dword pointer FS:[eax]; // loads link to previous registration and
mov FS:[eax], esp // puts link to the new registration in its place

Apart from putting the frame base ptr on stack, all this is exactly as per
Matt Pietrek's description of 'pure' SEH, ie not compiler enhanced SEH. An
Exception Registration Record (ERR) consisting of two dwords is created on
stack. . The first dword is the address of the exception registration
previous to this one. This address is to be found as the first dword in the
Thread Information Block (TIB) of the thread executing the code. The OS
keeps a reference to the TIB in the FS register. The second dword of the ERR
is the address of the exception handler. On the last line, the address of
the new ERR is written to the TIB. (remember the stack grows downward by
predecrementing :-))

Immediately in line with the code being protected, which in this case is
simply loading a few params to the fpu and waiting for a result, is the
cleanup code for the ERR.......

xor eax,eax;
pop edx;
pop ecx;
pop ecx;
mov FS:[eax],edx;
jmp normal_exit_code

This code clears the ERR from stack, grabbing the address of the preceding
ERR in edx and restoring it to the TIB. Note that the frame base pointer
that was pushed onto stack is also cleared in this operation. The code then
jumps the exception handler to make a normal exit. If an exception is
triggered by the OS, this piece of code never runs.

[snip]

> It would be interesting to see what would happen if you had code after the
> End; of your try/except block...
>
> try
> this;
> except
> that;
> end;
> somethingelse;
>
> It should point to "somethingelse"...
>

Yep... we need to see how that bit works.

>
> >Immediately following this jump, there is inserted a jump to
> >NotifyAnyException which looks like being in the Delphi RTL,
>

> NotifyAnyException is in System.pas ...
> But why would it go there if the registration on the stack points to your
> handler function?
>

Good question... I haven't read the part of the article which deals with the
way compilers extend the 'pure' SEH mechanism. But the clue may well be
there.

>
> >then follows
> >the jump to HandleZeroDivide, followed by the normal exit code.
>

> That would be normal program execution...
>
> BTW... Are they jumps or calls in the exception block?
>

No. The code that is inline really only does try_stuff, division_stuff,
try_cleanup, jump to HandleDivideByZero, DoneExcept, end_stuff.

[snip]

> Now I wonder what this is up to and how much of it is really necessary.
>

If you consider just the very basic SEH functionality, then perhaps a lot of
it is redundant. Certainly it's beginning to look like you could drop in
some assembler and get SEH running, but hacking into the elaboration created
to support the RTL and VCL is going to be quite an exercise.

Dave


Maarten Wiltink

unread,
Jun 27, 2004, 12:29:07 PM6/27/04
to
<nob...@noplace.not> wrote in message
news:omtrd0drrs9gd7d0m...@4ax.com...

> On Sat, 26 Jun 2004 23:16:26 +0100, "Martin Harvey (Demon Account)"
> <martin@_nospam_pergolesi.demon.co.uk> wrote:

>> There's a difference between Delphi language exceptions and OS
>> exceptions
>

> Only because borland says there is. Windows provides a native ability
> for application raised exceptions (look up RaiseException in the sdk)
> which follows the same course as all other exceptions. Why Borland
> would plug in 2500+ lines of code instead of using that is beyond me...
> but that's what they did.

Because Borland wants exceptions to be objects, is my guess. It does
not have the tell-tale T in front, but Exception is a classtype and
the "on Instance: ExceptionClass" syntax works polymorphically.

Groetjes,
Maarten Wiltink


Maarten Wiltink

unread,
Jun 27, 2004, 12:33:01 PM6/27/04
to
"J French" <ere...@nowhere.com> wrote in message
news:40dedbd4....@news.btclick.com...
[...]

> Elegant, compact and bugfree,
> it means nothing to me
> if it doesn't have EIP
>
> What does Terry mean - is he saying 32bit Ok, 16 bit not ok ?

Four bytes good, two bytes bad.

Groetjes,
Maarten Wiltink


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

Rob Kennedy

unread,
Jun 28, 2004, 12:44:40 AM6/28/04
to
nob...@noplace.not wrote:

> On Sun, 27 Jun 2004 18:29:07 +0200, "Maarten Wiltink"
> <maa...@kittensandcats.net> wrote:
>> Because Borland wants exceptions to be objects, is my guess. It does
>> not have the tell-tale T in front, but Exception is a classtype and
>> the "on Instance: ExceptionClass" syntax works polymorphically.
>
> Which... far as I can tell, and given what David and I've been exploring
> together... is TOTALLY unnecessary.

How do you figure?

I don't take advantage of polymorphic exception types very often, but
I'm glad they're available for the few times I need them. Even without
the polymorphism, it's still handy to have exceptions as objects. It
lets me pass additional information about the exception, usually in the
form of a custom error message or an error-code field, from the routine
that generated the exception to the routine that ultimately handles the
exception.

Some of Delphi's exception code is there to facilitate integration with
the debugger. Some of it is to wrap non-Delphi exceptions into objects
-- that includes both OS exceptions and C++ exceptions, neither of which
are compatible with Delphi exception objects. Some of the code is to
allow raising an exception from within an exception handler. Some of the
code is for parallel operation with Kylix, which has very different
exception-handling internally but still exhibits very similar behavior
from the programer's perspective.

--
Rob

Message has been deleted

J French

unread,
Jun 28, 2004, 3:16:04 AM6/28/04
to

As long as the pigs keep off the whisky

Maarten Wiltink

unread,
Jun 28, 2004, 3:28:21 AM6/28/04
to
<nob...@noplace.not> wrote in message
news:p2dvd053l7u7oiue6...@4ax.com...

> On Sun, 27 Jun 2004 23:44:40 -0500, Rob Kennedy <m...@privacy.net> wrote:
>> nob...@noplace.not wrote:
>>> On Sun, 27 Jun 2004 18:29:07 +0200, "Maarten Wiltink"
>>> <maa...@kittensandcats.net> wrote:

>>>> [...] Exception is a classtype and


>>>> the "on Instance: ExceptionClass" syntax works polymorphically.
>>>
>>> Which... far as I can tell, and given what David and I've been
>>> exploring together... is TOTALLY unnecessary.
>>
>>How do you figure?
>

> Well, as I said going into this, I figure OOP has it's place but not
> at the LAnguage or OS level. The closer you get to the hardware the
> less useful it becomes. Language, keywords especially, should be
> packed into the tiniest bundles possible. Core functionality, such as
> memory management or exception handling should be done by the OS, not
> the language. In this way you produce a programming environment that
> allows far more flexibility in creating powerful, fast and small end
> user apps.

How are exceptions not part of the language? When my parser finds the
input invalid, it doesn't merely crash with an error code E_SYNTAXERROR.
It throws an EParsingError exception with properties set for the file
and line and column where it had to stop, and why.

I like this. It's flexible and powerful in my book, it's fast enough,
and who cares about small?


> If I want an exception to appear as an object, *I* will wrap it up as
> such...

And I applaud you for it, but *I* don't know how. That's not to say that
I wouldn't be able to come up with something if I had to, but that I
don't need to now. This is called progress. It comes at a cost, sure, but
my time is more expensive than the time of even a thousand machines.

Groetjes,
Maarten Wiltink


Bruce Roberts

unread,
Jun 28, 2004, 10:25:01 AM6/28/04
to

"Maarten Wiltink" <maa...@kittensandcats.net> wrote in message
news:40def6c0$0$42417$e4fe...@news.xs4all.nl...

> Four bytes good, two bytes bad.

Depends on who is being bitten :).


Bruce Roberts

unread,
Jun 28, 2004, 10:37:43 AM6/28/04
to

"Terry Russell" <troc...@oRpEtMuOsVnEet.com.au> wrote in message
news:40de76c9$0$16104$afc3...@news.optusnet.com.au...

> At 18 you have 1 billion seconds of working life left.
> At average wages one second of your time is now worth
> 4 megabytes of permanent storage
> 2 Gigaflop
> All code is a waste of time, unless this is what you really _want_ to do
> as opposed to what you want the code to do.

Well put.


Martin Harvey (Demon Account)

unread,
Jun 28, 2004, 4:18:10 PM6/28/04
to
On Sun, 27 Jun 2004 15:55:40 -0400, nob...@noplace.not wrote:

>Which... far as I can tell, and given what David and I've been exploring
>together... is TOTALLY unnecessary.

No it's not. It has a good purpose, a lot of the code that is there is
to reduce heap fragmentation, which tends to be a lot worse for delphi
style allocations if you just use the native win32 functions.

Your replacement memory allocator actually isn't at all - it just
delegates the responsibility another level.

Before slagging off the borland code, why not actually learn a little
about memory allocation algorithms, and write yourself a proper heap?

MH.

Martin Harvey (Demon Account)

unread,
Jun 28, 2004, 4:27:57 PM6/28/04
to
On Mon, 28 Jun 2004 02:46:12 -0400, nob...@noplace.not wrote:

>But these practicalities when tucked into the middle of a programming
>language (and heaven forbid, an OS) seem to do nothing more than bloat the
>system, slow things down and limit the flexibility of it.

System time is cheaper than programmer time. Things have been done the
way they have because it saves people time. The fact is that just
about all sortware developers need to make money - they get that from
shipping products - they reduce the amount of costly engineering
effort making those products by providing common frameworks.

And hey - Delphi isn't very bloaty, compared to most software out
there - I'm writing my software to work fine on a ten year old P90,
and the delphi compiler is still lightning speed.

>My alternative memory manager stands as an example. It's smaller, it's
>simpler, its faster, it uses OS native management features and you can still
>treat memory as an object if you want to by defining methods to allocate,
>reallocate and fee memory for you.

Yeah, abd I promise you, if I put it into my current application and
leave it running for a few weeks, it'll get the machine crawling for
sure.

Theres a difference between best case cost or trivial cost, and
amortized worst case cost.

>If I want an exception to appear as an object, *I* will wrap it up as

>such... I don't want the language doing it for me, or worse still, wasting
>time and space in the process of giving me no choice but...

It does it for an excellent reasons - C++ lets you throw just about
anything, but I've seen some spectacular crashes when programmers
don't know how to handle what they think they're catching.

It's all to do with making the simple things simple - something that
Borland understands perfectly well - and their reputation for making
stuff "easy to pick up and run with" is what sells copies of their
software.

>Who knows, maybe I'm a throwback or something, but I still mostly program
>procedurally.

Look - it's like a double edged sword. The whole point of putting all
that architecture is not just to add features - it's also to constrain
developers. This is in fact a *good thing* - it reduces the number of
possible cockups they might make.

Think of it like this: the aim of the game of programming is not just
to add behaviour, it's actually to subtract behaviour: that is, the
entropy of a well designed system is less than that of the system in
it's primordial state. The more you constrain the number of ways you
can do stuff, the less likely it is that people will screw up.

>I write nicely featured music players in under 100K, console
>diagnostics in 32K, GUI utilities in 100k or less. My current "big" project
>is a Midi file editor/mixer/player with a gazillion features that I fear is
>going to reach the astronomical size of about 250K.

Yep - and how much more happier would you be to write it in half the
time, and get all those extra months of sales?

MH.

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

Jeremy Collins

unread,
Jun 29, 2004, 3:59:21 AM6/29/04
to
nob...@noplace.not wrote:

> On Mon, 28 Jun 2004 21:27:57 +0100, "Martin Harvey (Demon Account)"
> <martin@_nospam_pergolesi.demon.co.uk> wrote:

>>Think of it like this: the aim of the game of programming is not just
>>to add behaviour, it's actually to subtract behaviour: that is, the
>>entropy of a well designed system is less than that of the system in
>>it's primordial state. The more you constrain the number of ways you
>>can do stuff, the less likely it is that people will screw up.
>
>

> This is true. But it also limits one's creative abilities and programming
> is as much art as science. As my partner describes it: Programming is the
> art of getting computers to do things you know absolutely nothing about.

I have to jump in here. The only creativity that /users/ care
about is in well designed interfaces, and innovative products.

No-one apart from you and your team really cares about creative
code, and it is of course possible to write high quality code
in a RAD environment. The RAD environment or framework allows
you to get a creative product completed more quickly and
safely.

--
jc

Remove the -not from email

Maarten Wiltink

unread,
Jun 29, 2004, 4:01:25 AM6/29/04
to
<nob...@noplace.not> wrote in message
news:otc1e0dscufp2gss0...@4ax.com...

<code generated for try-except-end and try-finally-end>

I had actually expected the two cases to look more like each other.
It occurred to me a couple of days ago that try-except and try-finally
need not be implemented very differently. Both need to jump to a
section of code that executes, perhaps checking if it should, then
either cleans up the exception status or doesn't, and continues.

Perhaps it's a little too idealistic for real compiler writers. I know
that it always bugged me that only one of two different things may
happen after a try statement.

Groetjes,
Maarten Wiltink


Message has been deleted
Message has been deleted

Jeremy Collins

unread,
Jun 29, 2004, 5:46:19 AM6/29/04
to
nob...@noplace.not wrote:

> I've also never figured out why you can't use
>
> Try
> My_Code;
> Except
> My_fixups;
> Finally
> My_cleanup;
>

That would certainly be useful; I assume you intend that
the "finally" block isn't executed after an exception [1],
otherwise you'd probably have to allow this as well:

try
my_code;
finally
my_cleanup;
except
my_fixups;

Since "my_cleanup" could be trying to release memory that failed
to be allocated.

[1] This creates a bit of a language problem in itself, doesn't
it?

David Reeve

unread,
Jun 29, 2004, 6:00:42 AM6/29/04
to
<nob...@noplace.not> wrote in message
news:otc1e0dscufp2gss0...@4ax.com...
> On Sun, 27 Jun 2004 15:22:24 GMT, "David Reeve" <dree...@big-pond.net.au>
>
Laura,

I'm up to my neck in crocodiles so won't have a lot of time for this until
the weekend. I would like to get to the stage where I can invoke the OS SEH
mechanism by dropping in some assembler. Not that this is something I have
any need for, just curiosity. Commercial imperative puts me firmly in the OO
bloatware camp :-), and that's not because I've got my arm held up my back.
Like you, my background is in low level and procedural stuff, but I just
love the way I can take an abstract notion and make it a real engineering
entity based on good ole TObject. But, it's also very good to gain as much
understanding of the OS as one possibly can so let's go .....

> If I am reading this correctly...
>
> When you set up try/except:
>
>
> Try // 1 pushes SEH pointer to 4 on the stack

and links this exception record to the top of the exception chain

> // 2 falls through to your_code
>
> your_code;

unlinks exception record and cleans stack
>
> except // 3 jump to the more_code if no exception
> // 4 On exception does HandleAnyException
> // 5 On return goes to your_fixups.
>
> your_fixups;
>
> end; // 6 calls DoneExcept in system.pas
> // 7 goes to more_code if exception handled
>
> more_code;
>
>

This is a basic framework, but doesn't cover things like what happens if the
exception isn't handled? Not to mention all the exception filtration stuff.

>
> When you set up try/finally:
>
> Try // 1 pushes SEH pointer to 6 on the stack.
> // 2 falls though to your_code
>
> your_code;
>
> finally // 3 places address of more_code on the stack
> // 4 if no exception falls through to do_anyway
>
> do_anyway;
>
> // 5 jump to more_code if no exception
> end; // 6 on exception does HandleFinally in system.pas
> // 7 jumps to D0_anyway
>
>
> more_code;
>
>

I've had a quick step through this, and it seems to be much as you say.
However, I haven't looked very closely.

Dave

Maarten Wiltink

unread,
Jun 29, 2004, 6:25:50 AM6/29/04
to
"Jeremy Collins" <jd.co...@ntlworld-not.com> wrote in message
news:dMbEc.178$dm1...@newsfe6-gui.server.ntli.net...
> nob...@noplace.not wrote:

<try-except-finally-end statement>

> That would certainly be useful; I assume you intend that
> the "finally" block isn't executed after an exception [1],

HELL no! The finally clause is _always_ executed. If it should
be skipped in case of an exception, append it to the try clause.


> otherwise you'd probably have to allow this as well:
>
> try
> my_code;
> finally
> my_cleanup;
> except
> my_fixups;

I would expect the except clause to run before the finally clause,
so I would require the other order.


> Since "my_cleanup" could be trying to release memory that failed
> to be allocated.

That can always be fixed, and if it needs to, it should anyway.
I don't exactly see a scenario where memory could be or fail to be
allocated in the manner you imply.

Try statements already sometimes require constructions like

Ref:=nil;
try
...
Ref:=Allocate;
...
finally
if (Assigned(Ref)) then Free(Ref); { or possibly FreeAndNil }
end;

to get rid of the compiler warning about Ref possibly not having been
initialised, when human intelligence knows that can't happen. The
introduction of a generalised try-except-finally-end statement does
not change this in any way I can see - counterexamples are welcome.

The whole idea seems to be more marginal the more I think about it.
Assuming the semantics of the except clause going before the finally
clause, it's equivalent to a try-except statement nested inside a
try-finally statement. This might make an argument both for and against
extending the try statement. It's not hard, but neither does it add
much.

Groetjes,
Maarten Wiltink


Message has been deleted

J French

unread,
Jun 29, 2004, 8:15:19 AM6/29/04
to
On Tue, 29 Jun 2004 04:30:42 -0400, nob...@noplace.not wrote:

<snip>

>
>Please understand this, Jeremy... I'm not saying otherwise. I've done some
>work with RAD myself. All I'm saying is there's still a place where really
>tight procedural code pays off, too.
>
>It's not an either-or thing.

It is a 'horses for courses' thing

And sometimes a well trained 'horse' is appropriate for what looks
like an inappropriate 'course'
- normally when one has developed a solid library


Message has been deleted
Message has been deleted

J French

unread,
Jun 29, 2004, 9:33:52 AM6/29/04
to
On Tue, 29 Jun 2004 08:22:16 -0400, nob...@noplace.not wrote:

<snip>

>Oi... have I got some units! [grin]

You seem to have popped up here relatively recently
- yet also seem to have got your 'specialist area' well nailed down

Why the need for the NGs ?

Also have you looked at WDOSX for the command line stuff ?
- that I find very interesting (but I still yearn after a 32bit MSDOS)

Message has been deleted

J French

unread,
Jun 29, 2004, 10:38:19 AM6/29/04
to
On Tue, 29 Jun 2004 09:48:43 -0400, nob...@noplace.not wrote:

<snip>

>>You seem to have popped up here relatively recently
>>- yet also seem to have got your 'specialist area' well nailed down
>

>I guess I do, at that. Been messing with computers in one way or another as
>long as they've been around. By boyfriend got me started in the early 70s
>when he bought an Imsai 8080 that I learned to program with the paper tape.
>Been at it pretty much ever since.

Jezu - my intro was 1977 on a teletype with APL
- next ( IIRC ) a PET fell into my hands
- It took me until about 1987 to get into device drivers, TSRs etc

>>Why the need for the NGs ?
>

>Y'know what... I've learned quite a bit since I've been here. I don't much
>with the VCL so this is educational for me.

Smart bunch here

>You wouldn't be asking me to leave, now would ya??? [grin]

Ask Maarten about Esther

>>Also have you looked at WDOSX for the command line stuff ?
>>- that I find very interesting (but I still yearn after a 32bit MSDOS)
>

>No I haven't... Got links?? It would at least be worth a look.

http://www.dwp42.org

Impressive stuff - trouble is I want idiots to maintain my code

>The command line work I was doing was pretty much a one-off. A local
>computer store had a whole mess of p1 and p2 computers they were donating to
>the local AIDS outreach and wanted some "quick and dirty" diagnostics to
>check them out with. Half of them didn't even have CD roms, so the floppy
>thing came about. I really doubt it will become anything more than a rare
>sidetrip...

Ah - normally there, make the punter plug in a board

But I sort of see the problem ...

Coder outlook diversity is generally productive
- willkommen - bien venue - Gruess Gott ...


Rob Kennedy

unread,
Jun 29, 2004, 11:58:03 AM6/29/04
to
Maarten Wiltink wrote:
> I had actually expected the two cases to look more like each other.
> It occurred to me a couple of days ago that try-except and try-finally
> need not be implemented very differently. Both need to jump to a
> section of code that executes, perhaps checking if it should, then
> either cleans up the exception status or doesn't, and continues.

They're really more similar than the code lets on. The try-except code
generates a jump to HandleAnyException or HandleOnException. The
try-finally code generates a jump to HandleFinally. Those three routines
all do very similar things.

The major difference (at least in the compiler-generated code) is in
where the "try" statement tells the OS to jump to in the event of an
exception. Try-except jumps to the top of the "except" block;
try-finally jumps to the bottom of the "finally" block (both
destinations correspond to the location of the jump to HandleXXXX). The
"up-side down" try-finally handling, presumably, is to allow normal,
non-exception, execution to proceed as smoothly as possible.

The problem, for someone looking to rewrite Delphi's exception-handling
routines, is not so much in understanding the compiler-generated code
but in understanding what's going on inside System.pas and SysUtils.pas.
Two things making it difficult to read are that it's in assembler and
that there are several places that use JMP to go to another subroutine
instead of using CALL -- it's like following goto-laden code.

> Perhaps it's a little too idealistic for real compiler writers. I know
> that it always bugged me that only one of two different things may
> happen after a try statement.

Well, how many other things did you want?

--
Rob

Rob Kennedy

unread,
Jun 29, 2004, 12:06:59 PM6/29/04
to
David Reeve wrote:
> This is a basic framework, but doesn't cover things like what happens if the
> exception isn't handled? Not to mention all the exception filtration stuff.

Well, the code as shown *doesn't* filter any exceptions. The way to
filter exceptions in Delphi is by selecting a class of exception with
the "on" keyword. When you do that, the jump to HandleAnyException is
replaced with a call to HandleOnException. I'm not sure how that works,
though, since all the filtering code appears to be in HandleOnException,
not within the "except" block, so I don't know how HandleOnException
knows which exception classes to look for and where to jump when it
finds one it wants.

One way to not handle an exception is for the filtration to reject the
exception. I'm not sure what happens in that case. The other way to not
handle an exception is to reraise the exception with a sole "raise"
keyword. When you do that, Delphi looks at the next exception handler in
the chain and calls it. Although the SEH system allows an exception
handler to look at an exception and reject it, I don't think Delphi ever
does that. Instead, it walks the exception chain itself, and in doing
that, I think it has to replace some values in that chain so that when
the end is reached, the OS doesn't try to re-evaluate the chain. That's
the way it looked to me, anyway.

--
Rob

Message has been deleted

Rob Kennedy

unread,
Jun 29, 2004, 1:34:43 PM6/29/04
to
nob...@noplace.not wrote:
> Here's the prototype...
>
> function (Exceptrec : pexceptionrec; EstFrame : pointer;
> Contxt : pcontext; Dispcontxt : pointer) : longword;
>
>
> Exceptionrec is defined in the System Unit.
>
> ESTFrame is a pointer to the SEH record on the stack?

It's a pointer to an establisher frame; I'm not completely sure what
that means. It's not used in HandleAnyException, but it is used in
HandleFinally, which is called by HandleAnyException.

> The Context records are still something of a mystery but there
> is data present in at least the first 8 dwords of each record.
>
> The result value is one of:
>
> Exception_continue_execution = -1 == unwinding
> Exception_Continue_search = 0 == not handled
> Exception_Execute_Handler = 1 == handled
>
> (If I'm reading all this correctly... still not very confident with it)
>
> But then I hit a snag... In the OS the SEH pointer is *called* as a
> subroutine that enters at the jmp @handleanyexception instruction in the
> program. Ordinarily this wouldn't be a problem except that
> HandleAnyException never actually gets to the code beneath it... that's
> handled by an indirect jump mechanism I haven't fully fathomed yet.
>
> It would be a lot smarter if the HandleAnyException was a *Call* so that on
> return execution could simply continue with the instruction beneath it...
> but it isn't and it doesn't, so I'm still trying to get my head around it.

HandleAnyException *is* the exception handler. Therefore, the
compiler-generated code really can't use CALL to execute it.
HandleAnyException's return value needs to go to the OS, not to your
Delphi code.

I think I've figured out how the contents of the "except" block (and the
"finally" block) get called. It all happens in HandleFinally, and I
think that ends up being called within the context of RtlUnwind. The
address of @@returnAddress (a label in HandleAnyException) gets passed
to RtlUnwind. Eventually, control arives at that address (either by
RtlUnwind calling it or by RtlUnwind returning). It fetches a value from
somewhere on the stack -- ESP+8+8*4 -- which is the address of the
TExcFrame record passed to HandleAnyException by the OS. That record
contains the address of a TExcDesc record. That record just happens to
match the layout of the first two instructions in the "except" block --
the address is actually the same as the address pushed onto the stack
when entering the "try" block. The first instruction, as you've noticed,
is a JMP to HandleAnyException, and that's represented by TExcDesc.jmp.
The address of the TExcDesc.instructions field, therefore, is the
address of the next instruction, which is the first instruction for the
code you wrote in the "except" block.

TExcFrame is also used in the ClassCreate function to ensure that a
failed constructor calls the destructor.

>>This is a basic framework, but doesn't cover things like what happens if the
>>exception isn't handled? Not to mention all the exception filtration stuff.
>

> That's an interesting point... I think we have to make some basic
> assumptions:
>
> 1) Anything that comes up in the except part of a try/except structure is
> almost certainly going to be a result of something in the Try block. So we
> do need to try fixing it.
>
> 2) If we are going to write an Except block we pretty much obligate
> ourselves to deal with whatever's going on. Even if we end up with a Halt()
> in there.

Not always. Some exception handlers merely clean up and then reraise the
exception. The "try" block might have created an object, and the
"except" block will just free the object. It won't actually *handle* the
exception. (As far as SEH is concerned, though, the system probably does
consider the exception handled.)

> 3) There really isn't a high level code option way to say "no thanks" to an
> exception. (without really messing with the compiler) We might handle
> exception codes differently (Case ExceptCode Of) but we really don't have
> the mechanism to pass on them.

Yes we do. That's what "raise" is for.

> FWIW... I think this is what Borland is trying to accomplish with all those
> many many lines of code.

If the exception-handling code were in Pascal, I think you would be less
dismayed by how much of it there is. In assembler, just about anything
can look like a lot of code.

Large amounts of the code get skipped if a debugger isn't present. Some
of the code is there to hook into the callback functions that SysUtils
sets up and to do default handling if SysUtils' stuff isn't there.

> It seems they are trying to hand off exceptions we
> don't deal with in the ON exceptobject DO construct and then passing the
> stuff we don't explicitly handle back to the OS. This, I think, sounds good
> in theory, but it can lead to some pretty leaky handlers...

Leaky handlers? I'm not sure I follow you.

--
Rob

Rob Kennedy

unread,
Jun 29, 2004, 1:40:03 PM6/29/04
to
nob...@noplace.not wrote:
> Interesting... In my mind's eye I saw it kind of like this..
>
> Try
> Doing_This;
> Except
> That_Its_all_messed_up;
> Finally
> Take_the_Back_way_out;

Perhaps all this confusion about what try-finally-except and
try-except-finally would mean is an indication that it's better that we
don't have them. When you're forced to have try-finally and try-except
as separate constructs, then there isn't an confusion about which runs
first or about when each runs. The level of nesting determines the whole
thing at once.

--
Rob

Rob Kennedy

unread,
Jun 29, 2004, 2:57:41 PM6/29/04
to
nob...@noplace.not wrote:
> I think you'll find it uses 1 call to HandleAnyException which instantiates
> the exception objects and does some pretty heavy duty exception management.
> Each ON call will have it's on jump to HandleOnException with the exception
> object as a parameter pushed onto the stack.

No, I don't think that's what I'll find. In Delphi 5, the "try" block
pushes a pointer to the first line of the "except" block, and on that
line is a jump to HandleOnException. That is the only occurance of
"HandleOnException" in the code, and "HandleAnyException" does not
appear at all.

It's a little difficult to follow that code since when the "except"
block is filtered with "on" expressions, the "JMP HandleOnException"
line is not followed by executable code. Instead, it is followed by an
array of TExcDescEntry records that describe the exception types to look
for and the address of the code to call when an exception matches. Thus,
the debugger's decompiler gets confused about which lines are code and
which are data. It doesn't get re-synched with the source code until the
end of the procedure.

>>One way to not handle an exception is for the filtration to reject the
>>exception. I'm not sure what happens in that case.
>
>

> With the current setup if an exception is not handled the os gets
> "exception_continue_search" as a return from the DoneException call. In
> that case it goes into an unwind process (guarded in HandleAnyException) and
> will eventually fall into the unhandledexception filter placed at the base
> of the stackframe by windows.

My Delphi version has no DoneException call. It has a DoneExcept, but
that never returns anything. It's called at the end of the "except" block.

>>The other way to not
>>handle an exception is to reraise the exception with a sole "raise"
>>keyword.
>

> Actualy Rob, that's a means of re-creating it.

I don't think it is. To re-create the exception, you include the
exception object as an argument to "raise." It's the difference between
the compiler calling RaiseExcept or RaiseAgain. The former ends with a
call to RaiseException. The latter doesn't.

>>When you do that, Delphi looks at the next exception handler in
>>the chain and calls it. Although the SEH system allows an exception
>>handler to look at an exception and reject it, I don't think Delphi ever
>>does that.
>

> Yeah it does... It rejects C++ exceptions and those generated by DLLS it's
> using.

That's not how it looks to me. There is special handling for C++ Builder
exceptions, but that just wraps it into an Exception object with the
Message property "C++ exception." I also see nothing indicating that
Delphi checks the address of the exception to determine which module
generated it. An exception from a DLL is treated the same as an
exception from anywhere else.

I assert that Delphi never rejects an exception because the three
exception handlers (HandleAnyException, HandleOnException,
HandleFinally) always return 1 -- Exception_Execute_Handler.
HandleAutoException also returns 1, but I can't figure out when that is
ever called. I can't see where any of them ever return
Exception_Continue_Search. They do check for that return value from
UnhandledExceptionFilter, though.

Could it be that there were changes between Delphi 5 and whatever
version you're using?

--
Rob

Bruce Roberts

unread,
Jun 29, 2004, 2:48:45 PM6/29/04
to

<nob...@noplace.not> wrote in message
news:s6a2e0lgnu4s8ji2a...@4ax.com...

> I've also never figured out why you can't use
>
> Try
> My_Code;
> Except
> My_fixups;
> Finally
> My_cleanup;

I think the absence of this form of a Try was intentional.

While many associate Finally and Accept I think it quite clear that the two
statements have no intrinsic linkage. One uses Finally to protect resources
and Except to react to unusual events. Having the language suggest that the
two are somehow related promotes, IMO, a very poor paradigm.

It might have been better had the authors of Delphi not used Try with
Finally. I would have preferred to see something like

Do <statements> Finally <statements> End

This would have, IMO, clarified use of the statement and prevented the
unfortunate belief some have that Try Except and Try Finally should be used
together.


Martin Harvey (Demon Account)

unread,
Jun 29, 2004, 4:05:53 PM6/29/04
to
On Tue, 29 Jun 2004 09:48:43 -0400, nob...@noplace.not wrote:

>The command line work I was doing was pretty much a one-off. A local
>computer store had a whole mess of p1 and p2 computers they were donating to
>the local AIDS outreach and wanted some "quick and dirty" diagnostics to
>check them out with. Half of them didn't even have CD roms, so the floppy
>thing came about. I really doubt it will become anything more than a rare
>sidetrip...

If you want a function O/S on a floppy, then why not try Linux. You
can get a working linux kernel (yes, 32 bit, multitasking and all)
basic filesystem and display drivers, and a few utils up and running
on only a single 1.4meg floppy. At my previous job, I used to use
precisely such a linux boot disk to re-image PC's whenever we wanted
to run release tests with known good configurations.

Given your liking for lots of functionality in a tiny space, I think
it'll be just your thing :-)

Methinks it'll be a while before the XP kernel can be reduced to that
size.

MH.

Martin Harvey (Demon Account)

unread,
Jun 29, 2004, 4:07:50 PM6/29/04
to
On Mon, 28 Jun 2004 17:02:37 -0400, nob...@noplace.not wrote:

>Pointers, records, classes and objects do not get along well with heap
>defragmenters as they are fixed location references. Moving them on the
>heap (as you can with localalloc or globalalloc calls) invalidates them and
>delphi gets very lost very fast.

Uh oh ... you're giving me some ideas. The source code for FPC is
freely available is it not?

Hmm... we could take the source code for that, and modify it so it's a
garbage collected language, and where you *are* allowed to move blocks
of memory (involve a bit of compiler magic to keep track of all the
references).

Now that would be a *fun* project :-)

MH.

Martin Harvey (Demon Account)

unread,
Jun 29, 2004, 4:11:23 PM6/29/04
to
On Tue, 29 Jun 2004 12:25:50 +0200, "Maarten Wiltink"
<maa...@kittensandcats.net> wrote:

>to get rid of the compiler warning about Ref possibly not having been
>initialised, when human intelligence knows that can't happen. The
>introduction of a generalised try-except-finally-end statement does
>not change this in any way I can see - counterexamples are welcome.

You're right, it doesn;t since on a "try ... except ... finally"
construct, when entering the finally block, the compiler can;t
determine whether the "except code" has executed or not.

Additionally, what are you going to do about exceptions that get
raised in the except block.... are they trapped in the finally too??

mh.

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

Rob Kennedy

unread,
Jun 30, 2004, 12:06:44 AM6/30/04
to
nob...@noplace.not wrote:

> On Tue, 29 Jun 2004 13:57:41 -0500, Rob Kennedy <m...@privacy.net>
> wrote:
>> It's a little difficult to follow that code since when the "except"
>> block is filtered with "on" expressions, the "JMP
>> HandleOnException" line is not followed by executable code.
>> Instead, it is followed by an array of TExcDescEntry records that
>> describe the exception types to look for and the address of the
>> code to call when an exception matches.
>
> So it's a kind of "Case ExceptionCode Of" statement... Which, again
> suggests a somewhat simpler way...

If case statements worked on class references, I suspect the
implementation would be similar. It has to check not only the case
operand's type for a possible match, but also all of the operand's
ancestor types.

--
Rob

Message has been deleted

Rob Kennedy

unread,
Jun 30, 2004, 12:44:36 PM6/30/04
to
nob...@noplace.not wrote:
> So, don't use classes there. Just load the exception code into a
> variable.

Codes aren't polymorphic. You can't trap the division-by-zero error code
by checking for the math-error code. You also can't pass additional
object properties in an error code.

> For that matter, why not just use the WinApi GetExceptionCode call to
> fetch it?

Have you tried calling that?

It doesn't exist. It's documented in the API, but it's a macro. It
accesses an intrinsic variable in Microsoft's compiler implementation.

You can't "just" use it if you're forced to implement it for yourself first.

> I think this is what bothers me about the whole setup... it's
> horrificly complex when it just plain doesn't need to be.

Microsoft documented SEH completely interms of its own compiler. Much of
SEH's functionality is not actually provided by the operating system.

--
Rob

Rob Kennedy

unread,
Jun 30, 2004, 1:54:33 PM6/30/04
to
nob...@noplace.not wrote:
> Conceptually, Windows is calling a single subroutine to handle the
> exception. We are creating multiple calls and functions in the
> Except block. So Delphi tries to make them appear as a single
> subroutine. In fact, with just a few more bytes of compiler code,
> they could be framed as a single subroutine at compilation time. The
> only guard code it really needs is that of skipping the user code
> during OS unwinds and on-continuable exceptions; probably about 100
> bytes of machine code. This would eliminate the need for all that
> RTL code entirely. The expensive calls to create exception objects
> and destroy them could be coded as part of the user block... Leaving
> us the option to do it or not per the demands of the code we are
> creating.

One of the goals I think Delphi's developers had in mind was to minimize
the amount of code the compiler needs to generate on the fly. Instead,
it does only as much as it has to do and then delegates the rest of it
to prewritten RTL code. It just uses a handful of templates instead of
making something new for each exception block it encounters. The RTL
code is easier to update and fix. Borland doesn't have to teach the
compiler how to do the exception-filtering actions that the RTL does.

> ([grin] You could have the OOP convenience and I could have my
> smaller code)

But I'd have to write the objects myself. And so would anyone else who
wanted to use objects. So we'd have hundreds of people implementing the
same thing when Borland could have implemented it once and for all.

(Gee, I don't think I've ever used the expression "once and for all" so
literally before!)

> Anyhow... The OS passes control to HandleAnyException with the 4
> parameters we are presently examining... this first set of functions
> instantiate objects, decide what to about rewinds, sort out Dephi
> exception codes etc. and then, via a complex method I don't fully
> understand yet program flow is transferred to our code in the Except
> block falling eventually into DoneException (it's never directly
> called, it just happens next) where it's all cleaned up and control
> is passed back to windows. As far as the OS is concerned it was all
> done by one callback function...
>
> HandleAnyException + our code + DoneException == 1 callback.

Just in case you didn't think it was complicated enough, somewhere in
that "complex method," Delphi modifies the TExcFrame.desc pointer, sort
of creating a try-finally block of its own within the current exception
handler. That's to ensure that if the user exception code raises an
exception of its own (not the same as re-raising the current exception),
then the current exception object gets freed. It would be leaked, otherwise.

>> That record contains the address of a TExcDesc record.
>

> Which... strange as it may seem is actually stored in the TLS block
> created when a thread is launched. Hence the call to GetTls.

The call to GetTls, in the Delphi code, is to get the address of the
RaiseListPtr variable, which keeps a per-thread stack of exception
objects and addresses, allowing the ExceptObject and ExceptAddr
functions to work. (They might be Borland's version of the
GetExceptionCode and GetExceptionInfo API "functions.") I think any
other thread-specific information in the exception handler is fetched
directly from the Thread Information Block at FS:[0].

> Thing is I'm pretty sure that information is passed into the callback
> as part of the "establisher frame" parameter ...

Yep, that's exactly where it's passed in. The second parameter to
HandleAnyException, stored as [esp+8].

>> It won't actually *handle* the exception. (As far as SEH is
>> concerned, though, the system probably does consider the exception
>> handled.)
>

> Unless the callback code returns exception_continue_search the OS
> does indeed consider the exception handled. Notice that
> DoneException always exits with EAX = 1 ... the OS value for
> exception_continue_execution, signaling that the exception is
> handled.

Right, and so when a Delphi program is running, the OS will always view
an exception as handled, regardless of what Delphi really does with it.
That's what my point in the parenthetical was, anyway.

> It's an attempt at it... what Raise actually does is cause a whole
> new exception just like the original one. If not done carefully,
> this can result in duplicated, nested, exceptions. Check the WinApi
> call for RaiseException ... it gives some good clues to how that
> works.

"Raise," by itself, never calls RaiseException -- at least not for
anything beyond notifying the debugger of what's going on. The OS never
gets involved.

> Try running a small proggy without SysUtils loaded. The entire
> exception handling system dies... no syntax errors, it just doesn't
> do anything. Far and away the bulk of the exception code is in
> SysUtils... hundreds and hundreds of lines of it...

That's not the way it is in Delphi 5. The single longest procedure in
SysUtils is ExceptionErrorMessage. Next is MapException, which is only
long because it has a case statement mapping exception codes into
indices for looking up associated exception classes.

The bulk of the code is in System, which checks the procedure pointers
like ExceptObjProc, and if they aren't assigned, simply skip to the
bottom of the HandleAnyException procedure.

If most of the code has shifted into SysUtils, then it was probably in
conjunction with the splitting of the VCL and RTL run-time packages.

> Take a version of the RTL and define MSWINDOWS but not DEBUG in the
> makefile and it ends up being considerably smaller... it can't help
> but skip code that isn't there.

No can do. My System.pas has no conditional-define blocks. If I ever get
Delphi 7, I'll be sure to take a look at the changes to the exception
system.

> Ok... Lets say you're updating a disk file... there can be one of
> several things going wrong when you do that. The file might not be
> there, it might have i/o errors in it, it might be crosslinked, you
> might not have enough memory to load it, you might be out of
> diskspace, etc. All kinds of things can go wrong and a lot it might
> well be recoverable errors. Any exception handler that doesn't
> concisely deal with *every* possibility

The beauty of exceptions is that you never have to handle *every*
possibility. You can limit your handling to the situations that you know
how to handle in the current context. You can leave the other problems
for higher-level code to deal with.

> is going to end up handing unhandled exceptions back to the OS which
> is then going to consider them unhandled and will needlessly abort
> the thread presenting the user with what looks like a program crash.

When an exception occurs that you don't know how to handle, I don't
think it's unwarranted for the program to crash.

> I don't think it's unreasonable to describe a missed or skipped
> exception as leakage in that case.

Well, I've never considered a crashed program to be a leak. I consider
it a crash. If it's just a difference in terminology, then so be it.

--
Rob

Message has been deleted
Message has been deleted

Maarten Wiltink

unread,
Jul 1, 2004, 4:16:57 AM7/1/04
to
<nob...@noplace.not> wrote in message
news:h1c6e0983e3ivjsg3...@4ax.com...
> On Wed, 30 Jun 2004 11:44:36 -0500, Rob Kennedy <m...@privacy.net> wrote:

>> Codes aren't polymorphic.
>
> Maybe it's just me, but I don't see that as a problem.

There are different types of programmers. You are placing yourself
in the system programmer camp. People from the application programmer
camp, on the other side of town, like their on EMathError clauses to
catch EDivideByZero as well. It's an OO thing; it matches the way we
think well.


[...]
> It's really not much of a problem to add these things and you only
> have to do it once, Rob.

Make that "you only have to do it once, Borland." They can do it even
oncer than any and all of us could.

Groetjes,
Maarten Wiltink


Message has been deleted

Jeremy Collins

unread,
Jul 1, 2004, 8:28:34 AM7/1/04
to
nob...@noplace.not wrote:

> I think I've added about 40 or 50 missing constants and a dozen or so api
> calls in the last couple of months.

Check out the JEDI project on SourceForge...


--
jc

Remove the -not from email

VBDis

unread,
Jul 3, 2004, 4:07:37 AM7/3/04
to
Im Artikel <lv5ud09fq5frvrpvn...@4ax.com>, nob...@noplace.not
schreibt:

>So... what we have so far is this:
>
>Try : sets up an exception registration on the stack but is
> otherwise benign.
>
>Except: sets up a jump around the contained code so that it's only
> entered by exception calls from the OS.
>
>Finally: ????

Finally: this code can be executed during normal processing and exception
handling as well. It can be considered as being an always failing exception
handler, i.e. it returns "exception not handled".

DoDi

VBDis

unread,
Jul 3, 2004, 4:07:38 AM7/3/04
to
Im Artikel <p2dvd053l7u7oiue6...@4ax.com>, nob...@noplace.not
schreibt:

>Well, as I said going into this, I figure OOP has it's place but not at the
>LAnguage or OS level. The closer you get to the hardware the less useful it
>becomes.

Just at OS level a bit more OOP could make the systems more stable. When Unix
was ported from ASM to C, the size decreased by 1/3 (or by 2/3?). I don't think
that it was the compiler, that created so much smaller code, but instead it was
less source code resulting from a better design model. Similar effects, like
decreasing the bug rate considerably, could result from introducing OO instead
of weak languages.

And when you look at the OS services, you'll find objects or "handles" all
over. Files are objects, processes are objects, memory management is based on
objects, Windows messages are objects. It's simply inconsequent to implement
and use objects without an OO language. Have you ever forgotten to close files
or to free memory, exactly once? An appropriate object management, including
automatic calls to default constructors and destructors, would make it
impossible to work with uninitialized or already destroyed objects, or leave
something unfinalized.

>Language, keywords especially, should be packed into the tiniest
>bundles possible.

Tell that Intel, with regards to the 80x86 instruction set. They'll respond
that certain operations can be handled better by special instructions, than by
a sequence of instructions of a restricted instruction set. Even if I do not
fully agree, at least with regards to instruction sets, a compiler can optimize
the code the better the more complex and carefully designed constructs are part
of a language.

>Core functionality, such as memory management or
>exception handling should be done by the OS, not the language. In this way
>you produce a programming environment that allows far more flexibility in
>creating powerful, fast and small end user apps.

That's a good idea, an OS should be as complete as possible, but is against any
portability. Try to make work GNU code, written for a POSIX OS, on Windows or
any other non-POSIX OS, and you're lost :-(

Most programming languages have their own philosophy with regards to exceptions
and other standard "objects". Many of these models are incompatible, no chance
for a common implementation in an OS. Even if .NET tries to provide the
mentioned services to all languages and applications, all programming languages
have to be modified for .NET compatiblity.

BTW, exception "handling" is part of an application, the OS only can define the
according objects (data structures and methods).

DoDi

Message has been deleted

David Reeve

unread,
Jul 3, 2004, 9:11:16 AM7/3/04
to

<nob...@noplace.not> wrote in message
news:h30de01c4ahojta44...@4ax.com...

> On 03 Jul 2004 08:07:38 GMT, vb...@aol.com (VBDis) wrote:
>
> >Just at OS level a bit more OOP could make the systems more stable. When
Unix
> >was ported from ASM to C, the size decreased by 1/3 (or by 2/3?).
>
> Ummm... while I don't doubt your word, how do you explain...
>
> Basic media player in OOP/VCL code == 1100k
> Same Basic player in proceural/WinApi code == 86k.
>
> Moreover the smaller one is noticeably faster and rock stable.
>
> Go Figger, eh?
>

I Figger it's rock stable because you're an exceptional programmer :-)
However, IMO Dodi's point stands. Could you manage a team of programmers to
do what you do, and still produce something rock stable? In twenty years of
programming I have come across very few people I would trust to with such
work and very many who could make a mess of 'hello world'. OOP doesn't make
a good programmer out of a bad one, but it does limit the scope of the
damage they can do to the overall project.

Dave


David Reeve

unread,
Jul 3, 2004, 9:29:39 AM7/3/04
to
"Bruce Roberts" <b...@bounceitattcanada.xnet> wrote in message
news:PSiEc.63$gy2....@news20.bellglobal.com...
[snip]

>. One uses Finally to protect resources
> and Except to react to unusual events. Having the language suggest that
the
> two are somehow related promotes, IMO, a very poor paradigm.
>
> It might have been better had the authors of Delphi not used Try with
> Finally. I would have preferred to see something like
>
> Do <statements> Finally <statements> End
>
> This would have, IMO, clarified use of the statement and prevented the
> unfortunate belief some have that Try Except and Try Finally should be
used
> together.
>

Interesting point. Language conveys meaning in very subtle ways, even a
language made of a few keywords. It is one thing for the designers to make
the intended use clear in documentation, it is another to make it flow
naturally from the correct choice of keyword. I just feel the ambiguity
leaking in at the very thought of combining these constructs.

Dave.


David Reeve

unread,
Jul 3, 2004, 10:42:35 AM7/3/04
to
"Rob Kennedy" <m...@privacy.net> wrote in message
news:2kdsd4F...@uni-berlin.de...

[snip]

I've missed most of this heavy duty thread and am only just trying to get my
head around what is being said, and its past midnight already :-(


> I assert that Delphi never rejects an exception because the three
> exception handlers (HandleAnyException, HandleOnException,
> HandleFinally) always return 1 -- Exception_Execute_Handler.
> HandleAutoException also returns 1, but I can't figure out when that is
> ever called. I can't see where any of them ever return
> Exception_Continue_Search. They do check for that return value from
> UnhandledExceptionFilter, though.
>
> Could it be that there were changes between Delphi 5 and whatever
> version you're using?
>

For what its worth, I was writing a lot of Delphi dlls in D4 and D5 to
support some old code we had written in CVI C. Now CVI didn't implement SEH,
and if you called a function from the delphi dll, and that function raised
an exception, the stack ended up being completely unwound and the you got
the "program has performed an illegal operation...." message as the app
closed. When I bracketed all my exported functions in try..except blocks
every exception was trapped. So I go along with the contention that a Delphi
app never rejects an exception.

Dave


Message has been deleted
Message has been deleted

VBDis

unread,
Jul 7, 2004, 5:21:17 AM7/7/04
to
Im Artikel <9721e0dalprpdigh5...@4ax.com>, nob...@noplace.not
schreibt:

>Programming is the
>art of getting computers to do things you know absolutely nothing about.

;-)

DoDi's extension:

Programming is the art of getting computers to produce inexplicable situations
you never met before.


For some people this may be the salt of life...

DoDi

VBDis

unread,
Jul 7, 2004, 5:21:16 AM7/7/04
to
Im Artikel <rti3e0t8jh7m6tjff...@4ax.com>, "Martin Harvey (Demon
Account)" <martin@_nospam_pergolesi.demon.co.uk> schreibt:

>Hmm... we could take the source code for that, and modify it so it's a
>garbage collected language, and where you *are* allowed to move blocks
>of memory (involve a bit of compiler magic to keep track of all the
>references).

This is what you can get with .NET (Delphi 8).

>Now that would be a *fun* project :-)

Have a look at the DotGNU project, bringing .NET to Unix platforms, and in a
Microsoft-independent version to Windows. It's not a fun project, many
excellent people contribute already to this project. If ever, I'd spend my time
in supporting the DotGNU development team.

DoDi

VBDis

unread,
Jul 7, 2004, 5:21:17 AM7/7/04
to
Im Artikel <40e121d5$0$568$e4fe...@news.xs4all.nl>, "Maarten Wiltink"
<maa...@kittensandcats.net> schreibt:

>Perhaps it's a little too idealistic for real compiler writers. I know
>that it always bugged me that only one of two different things may
>happen after a try statement.

As we've seen in the meantime the opinions differ about the execution order of
the except and finally parts. The current syntax allows to specify any order,
optionally with multiple except and finally guards around the same try code.

There exist more suggestions around guarding resources, with extensions to
try-finally. One suggestion is something like a initialize-use-finalize
construct, making it (almost ;-) impossible to forget to call FindClose after
FindFirst, or CloseFile after OpenFile, or to destroy other local objects
before leaving a subroutine. The syntax might be modified so that the required
initialization and finalization is specified first, because both are tightly
coupled. Then the reader or writer of the code can forget about the
finalization, and let it up to the compiler to insert the finalization code in
the appropriate place, after the last usage of the protected resource.

Such thoughts suggest to me that try-finally (or initialize-finalize or
protect-release...) should be separated from try-except exception handling.
It's only one minor aspect that the finally code also executes after an
exception, regardless of whether the exception is handled or not.

DoDi

Message has been deleted

Martin Harvey (Demon Account)

unread,
Jul 7, 2004, 3:04:51 PM7/7/04
to
On Wed, 07 Jul 2004 10:40:55 -0400, nob...@noplace.not wrote:

>I don't think you'll find this is correct. Delphi doesn't allow this:

Er, yes - he knows.

MH.

Message has been deleted
It is loading more messages.
0 new messages