What's wrong with just a runtime-checked const?

xs0 xs0 at xs0.com
Mon Jul 17 04:15:06 PDT 2006


>> - it can still be trivially subverted - just cast to int/long and back
> I presume this point leads on from the above, where you assumed that the 
> bit was stored *in* the pointer. So that's a null issue, since it 
> clearly isn't.

Well, it's not really important where it's stored - if you cast to 
int/long, you lose the constness information in any case...


>> - you can't just check at the beginning of a function
> I don't understand your reason for this, but when I started writing down 
> the details more specifically, I realised that the advantage of runtime 
> const checking is a *huge* increase in flexibility, and having to say at 
> compile-time whether a function is const or not removes that flexibility 
> in my mind.

Agreed :) It's definitely more flexible, but the question is whether the 
cost is low enough for the feature to still be usable, and whether it's 
realistically implementable at all.. Note that even if the GC is 
modified, and the constness information is stored somewhere externally, 
it can take a lot of updating when passing pointers/references around...


>> - you can get the pointer in the middle of it; you can also get the
>> pointer in _another_ function (from a global or in a multi-threaded
>> program); checking at every access would be too expensive, I think,
>> even for a debug build
> 
> I don't know how expensive it would be. Considering that all it is is
>   assert(!isConst);
> that operation doesn't seem too hard. And of course, the compiler is 
> free to optimize away duplicate versions of it, like this:
> 
>   _member = 4;
>   _member = 3;

Well, you assume the optimizer, but it's not usually used with debug 
builds, even if it supported this optimization.

And there definitely are cases where each access would require a check; 
in a multi-threaded program you can hardly assume anything about 
non-local variables, especially that they don't change :)


> Obviously there's no need to check isConst before the second assignment. 
> And on the issue of the pointer suddenly changing in the middle of the 
> function: well, it's actually not an issue, because I worked out that 
> it's best for the function to have a local copy of the isConst variable, 
> which means no other resources can change it (other than a malicious 
> hacker with pointers). This is also conceptually right, because it 
> doesn't make sense to give a function a certain level of modification 
> access and then change it while it is running.

That is true only for correct programs ;) Considering how the purpose is 
to catch bugs, though, you can't make that assumption...


> In my view, we either need runtime-checked const or nothing. Consider 
> this, and tell me how we can avoid excess dup calls if we use C++-style 
> const-checking:
> 
>  class foo {
>    private char[] _name;
>    public const char[] getName()
>    {
>      return _name;
>    }
>    ...
>  }
>  ...
>  Import std.string;
>  foo f;
>  /*const*/ char[] name = f.getName();
>  char[] name_m = tolower(name);
>  // Can we modify name_m? Better dup it, just to make sure
>  name_m = name_m.dup();

if (name_m is name)

but, it's certainly not a pretty solution... and there's a related 
question - how can tolower know whether to .dup or not.. there are 
certainly cases where it isn't necessary.


> With runtime const checking, we could fix that, though, by also getting 
> a bool variable back from tolower() which says whether it returned the 
> original string or a copy. Quite simply, compile-time const won't let 
> you do that, so you will actually produce *slower* code.

Well, if you wanted, you could make tolower() return that already, it 
doesn't have much to do with constness..

> If you're interested, I'm trying to come up with a draft which has the 
> actual details, jut so it gives a more solid ground for discussion. My 
> problem at the moment is just what we mentioned earlier: operability 
> between debug and release builds. I suggested that each function should 
> be passed, behind the scenes, the relevant isConst variable, but that's 
> not compatible with release builds. I then thought that you could have 
> two copies of a function: one for const variables and one for non-const 
> variables. The correct one would be chosen at runtime, and external 
> packages would always choose the one for non-const variables (which is a 
> copy of the one for const variables, but with checking turned off). This 
> effectively duplicates the amount of machine code generated by the 
> compiler, but I am convinced that a solution like I propose is much 
> better than a simple static checking scheme for the flexibility reason I 
> mentioned above.

Sure, I'm interested :) But the way I see it, it's a practically 
impossible problem to solve in a way that is time/space efficient, 
useful, and easy to use, even more so if the solution is not static..


xs0



More information about the Digitalmars-d-learn mailing list