Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2016-09

with no if assigned() there are bugs

15 messages · 9 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Lars

Hi all, I am wondering what your thoughts are on this idea: add the ability to do if assigned() on all objects to prevent bugs, maybe as a compiler feature. Before you write me off as just another person requesting yet another silly feature (it may in fact be that), here is the problem:

A lot of "other people's code" I deal with, has access violations. When I try to debug the application code, I waste hours of my time, only to find out that it was that common bug: a person forgot to check

if assigned(SomeObject)

before accessing the object properties or fields. i.e. the access violation was because of referencing an invalid (non existing) object.

So what if the compiler had an option to check if assigned, before accessing any object. This would seem to be like a performance hit however I'm not sure that an If check is that much of a waste of CPU power. It would be similar to range checking: yes, may be a performance hit, but increases safety of application.

If you downloaded some code and had an access violation, the first thing you would do is enable the compiler option to always if assigned() check automatically on all objects, recompile the app, and if the bug goes away you know it was because !someone! forgot to check "if assigned()" on an object before accessing it.

Would this be a good safety feature, in the spirit of range checks, and in the spirit of avoiding C like code (buffer over runs) because essentially this is unsafe C like programming to access a dead object, IMO.

With garbage collection you don't have this problem (maybe it creates other issues such as reusing objects you didn't really want to use). However as FPC and Delphi are likely not going to be garbage collected for some time, if ever, wouldn't this If Assigned check add one more reason to use FPC without the nasty access violations caused by non garbage collected programming?

I am open to being debated on this: I'm not 100 percent certain this feature would be as good as I make it out to be. Would it be hard to implement? I don't know.. an if check, automatically, before accessing an object.... Then also would you do performance optimizations to only call if assigned() once if a bunch of object fields are being accessed in a row such as:

stringlist.add('one')
stringlist.add('two')

Only one if assigned() check is needed before the above two calls, not a check each time stringlist.add is called. This performance optimization could be a worry later, and the first time if assigned() is implemented automatically by the compiler, performance is ignored. Plus this feature might just be a debug facility rather than something you enable when you ship the application.... similar to range checking (although some would argue range checking should ALWAYS be on and turning it off is silly).

What are your thoughts? Thing is, I've come across more than my fingers can count, of times that this bug has bit me, especially when I am downloading someone elses' code and haven't gone through thousands of source files looking to see that if assigned() was called.

Michael Van Canneyt
to Lars
Lars wrote 20 lines
Hi all, I am wondering what your thoughts are on this idea: add the ability to do if assigned() on all objects to prevent bugs, maybe as a compiler feature. Before you write me off as just another person requesting yet another silly feature (it may in fact be that), here is the problem: A lot of "other people's code" I deal with, has access violations. When I try to debug the application code, I waste hours of my time, only to find out that it was that common bug: a person forgot to check if assigned(SomeObject) before accessing the object properties or fields. i.e. the access violation was because of referencing an invalid (non existing) object. So what if the compiler had an option to check if assigned, before accessing any object. This would seem to be like a performance hit however I'm not sure that an If check is that much of a waste of CPU power. It would be similar to range checking: yes, may be a performance hit, but increases safety of application.

This would in general be a very bad idea.

If there is no 'If Assigned()', it means the person who programmed it, assumes the object is always valid at that point.
If it is not, you should ask yourself why it is not valid, and not hide the problem by adding "if Assigned()" automatically.

The -CR command-line option more or less does this, but I am not sure if it also checks field or property access.

Michael.

Tomas Hajny
to Lars: Hi all, I am wondering what your thoughts are on this idea: add the ability to do if…

On Wed, September 21, 2016 07:29, Lars wrote:

Hi,

Hi all, I am wondering what your thoughts are on this idea: add the ability to do if assigned() on all objects to prevent bugs, maybe as a compiler feature.

.
.

What would be the supposed "else" clause of your "if" statement? I assume that the original action with the given object should not be ignored silently, because that would lead to even more difficult debugging of such bugs. Run-time error? But that is already happening with access violation too. Or...?

Tomas

Mark Morgan Lloyd
to Tomas Hajny
Tomas Hajny wrote 16 lines
On Wed, September 21, 2016 07:29, Lars wrote: Hi, > Hi all, I am wondering what your thoughts are on this > idea: add the ability to do if assigned() on all > objects to prevent bugs, maybe as a compiler feature. . . What would be the supposed "else" clause of your "if" statement? I assume that the original action with the given object should not be ignored silently, because that would lead to even more difficult debugging of such bugs. Run-time error? But that is already happening with access violation too. Or...?

Presumably this would be an assertion that something is assigned. A related test is that an object is a specific subtype before using it as such

   Assert(PageControl1.ActivePage.Controls[0] is TSynEdit);
   syn := TSynEdit(PageControl1.ActivePage.Controls[0]);

but I'd suggest that this is as much a refactoring problem as one which should be tackled by the compiler.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]
Martin
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote 7 lines
Presumably this would be an assertion that something is assigned. A related test is that an object is a specific subtype before using it as such Assert(PageControl1.ActivePage.Controls[0] is TSynEdit); syn := TSynEdit(PageControl1.ActivePage.Controls[0]);

The problem is that even a test like that would NOT catch all cases.

syn.destroy;
Assert(syn is TSynEdit);

In this case, it is very likely that "syn is TSynEdit" still returns true. (no assertion thrown)

Simply because "syn.destroy;" does not wipe the memory clean. (depending on mem manager)

Using -gh
And (optionally) setting the environment HEAPTRC="keepreleased" (that is for debugging only)
http://www.freepascal.org/docs-html/rtl/heaptrc/environment.html will help.

On top of that you can use -CR

Also search suspected code for every "destroy" or "free" and, replace with FreeAndNil(var) if possible.

Mark Morgan Lloyd
to Martin
Martin wrote 16 lines
On 21/09/2016 09:05, Mark Morgan Lloyd wrote: > > Presumably this would be an assertion that something is assigned. A > related test is that an object is a specific subtype before using it > as such > > Assert(PageControl1.ActivePage.Controls[0] is TSynEdit); > syn := TSynEdit(PageControl1.ActivePage.Controls[0]); The problem is that even a test like that would NOT catch all cases. syn.destroy; Assert(syn is TSynEdit); In this case, it is very likely that "syn is TSynEdit" still returns true. (no assertion thrown)

Absolutely. But as you say later, anybody who doesn't use FreeAndNil() is asking for trouble.

Show quoted text 13 lines
Simply because "syn.destroy;" does not wipe the memory clean. (depending on mem manager) Using -gh And (optionally) setting the environment HEAPTRC="keepreleased" (that is for debugging only) http://www.freepascal.org/docs-html/rtl/heaptrc/environment.html will help. On top of that you can use -CR Also search suspected code for every "destroy" or "free" and, replace with FreeAndNil(var) if possible.

[From elsewhere a few years ago, somebody's wife looked over his shoulder and saw his Delphi code full of Create and Destroy calls. "Bit violent isn't it?" she remarked.]

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]
Pierre Free Pascal
to Martin: The problem is that even a test like that would NOT catch all cases. syn.destroy;…
Show quoted text 34 lines
-----Message d'origine----- De : [mailto:fpc-pascal- De la part de Martin Envoyé : mercredi 21 septembre 2016 12:38 À : FPC-Pascal users discussions Objet : Re: [fpc-pascal] with no if assigned() there are bugs On 21/09/2016 09:05, Mark Morgan Lloyd wrote: > > Presumably this would be an assertion that something is assigned. A > related test is that an object is a specific subtype before using it > as such > > Assert(PageControl1.ActivePage.Controls[0] is TSynEdit); > syn := TSynEdit(PageControl1.ActivePage.Controls[0]); The problem is that even a test like that would NOT catch all cases. syn.destroy; Assert(syn is TSynEdit); In this case, it is very likely that "syn is TSynEdit" still returns true. (no assertion thrown) Simply because "syn.destroy;" does not wipe the memory clean. (depending on mem manager) Using -gh And (optionally) setting the environment HEAPTRC="keepreleased" (that is for debugging only) http://www.freepascal.org/docs-html/rtl/heaptrc/environment.html will help.

There is also the -gc option:
-gc Generate checks for pointers

This is another debugging option, that is not used very often, so that it might not always work correctly, but it could be worth a try in your case.

It probably does not work well if threads are used, but in principle, it calls checkpointer function before any pointer dereference. The exact action of checkpointer depends on the operating system, the code is also in heaptrc.pp unit.

In the hope it will be useful,

Pierre Muller

Graeme Geldenhuys
to Pierre Free Pascal
Pierre Free Pascal wrote
There is also the -gc option: -gc Generate checks for pointers

Interesting, I didn't know about that option.

Unfortunately under CentOS 6 Linux I get:

Fatal: Option "-gc" is not, or not yet, supported on the current target platform

Do you know which platforms support the -gc option? Windows, FreeBSD?

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Pierre Free Pascal
to Graeme Geldenhuys

I assume that your system is a
x86_64-linux...

for linux, it seems only 32bit systems are supported, mainly because there is no stack validation code for 64-bit target...

The list of supported targets is in: systems_support_checkpointer

For version 3.0.0:
systems.pas:342: systems_support_checkpointer = [system_i386_linux,system_powerpc_linux]
systems.pas-343- + [system_i386_win32] systems.pas-344- + [system_i386_GO32V2] systems.pas-345- + [system_i386_os2] systems.pas-346- +
[system_i386_beos,system_i386_haiku]
systems.pas-347- + [system_powerpc_morphos];

Anyhow, this code seems also broken for i386-linux...

I just committed two fixes to trunk,
it is possible to cycle compiler now with -gc option on both i386 and x86_64 linux.
As the fix is not cpu specific, I enabled the -gc option for all linux systems in trunk, but this is untested.

So if you are using linux OS, -gc option is probably only usable starting with today's trunk commits.

Pierre

Show quoted text 33 lines
-----Message d'origine----- De : [mailto:fpc-pascal- De la part de Graeme Geldenhuys Envoyé : mercredi 21 septembre 2016 14:35 À : Objet : Re: [fpc-pascal] with no if assigned() there are bugs On 2016-09-21 13:27, Pierre Free Pascal wrote: > There is also the -gc option: > -gc Generate checks for pointers Interesting, I didn't know about that option. Unfortunately under CentOS 6 Linux I get: Fatal: Option "-gc" is not, or not yet, supported on the current target platform Do you know which platforms support the -gc option? Windows, FreeBSD? Regards, Graeme -- fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Graeme Geldenhuys
to Pierre Free Pascal
Pierre Free Pascal wrote
I assume that your system is a x86_64-linux...

Yup.

So if you are using linux OS, -gc option is probably only usable starting with today's trunk commits.

Thank you very much.

Regards,
Graeme

Jonas Maebe
to Pierre Free Pascal: I assume that your system is a x86_64-linux... for linux, it seems only 32bit systems are…
Pierre Free Pascal wrote
As the fix is not cpu specific, I enabled the -gc option for all linux systems in trunk, but this is untested.

Please never do that. I am the one that disabled this specific option in the past (and others too) because they had never been tested and were often broken. Enabling and releasing options without testing them at all just results in user frustration (because they rightfully expect that when we officially release something, it has at the very least been tested by one person).

Additionally, -gc does not work at all as soon as you link to an external library and access memory that has been allocated by this external library. As a result, I would strongly discourage using it at all, except in pure FPC programs.

Jonas

Lars
to Graeme Geldenhuys: Interesting, I didn't know about that option. Unfortunately under CentOS 6 Linux I get:…
Show quoted text 5 lines
On 2016-09-21 13:27, Pierre Free Pascal wrote: There is also the -gc option: -gc Generate checks for pointers

I was going to add to my original post "sorry if this feature already exists, or something similar".

Now I have to see what Delphi offers, as I use fpc and delphi and need this check on both systems!

p.s. unrelated off topic: someone said that Delphi Berlin Starter only works on Windows 10. I found it worked fine on my Windows 7, FYI. But I think the free offer (download) is over, or if not, shortly.

Lars
to Pierre Free Pascal: There is also the -gc option: -gc Generate checks for pointers This is another…
Pierre Free Pascal wrote 5 lines
There is also the -gc option: -gc Generate checks for pointers This is another debugging option, that is not used very often,

I could not find this option in the Lazarus options under debugging or any other tab... maybe it is not used often enough that Lazarus missed putting it in a compiler option configuration... or I may have missed it.

I think this is a good check to have.... So in Lazarus must I make my own custom option, or is it hidden somewhere where I cannot see it?

I should post this to lazarus list: in this case do I double post to both freepascal list and lazarus list, or better to just post a message to one list?

Thanx

Mattias Gaertner
to Lars
Show quoted text 11 lines
On Wed, September 21, 2016 6:27 am, Pierre Free Pascal wrote: > There is also the -gc option: > -gc Generate checks for pointers > > > This is another debugging option, that is not used very often, I could not find this option in the Lazarus options under debugging or any other tab... maybe it is not used often enough that Lazarus missed putting it in a compiler option configuration...

See Jonas comment, why -gc has limited use.

or I may have missed it. I think this is a good check to have.... So in Lazarus must I make my own custom option, or is it hidden somewhere where I cannot see it?

Many options have no GUI element. That's why there is Custom Options / All Options.

Mattias