[fpc-devel] Const optimization is a serious bug

Chad Berchek ad100 at vobarian.com
Mon Jul 11 02:45:36 CEST 2011


Sorry for the additional post; I should have added this to my preceding 
message.

I just want to clarify: I am trying to be very careful to distinguish 
between implementation and semantics.

If my understanding is correct, AnsiString implementation is always 
pass-by-reference.

The problem is the programmer should be forced to stick to certain 
semantics, not a certain implementation. With const AnsiString, the 
implementation is consistently pass-by-ref, but the semantics can change 
as described in my previous message, depending on the instance's 
refcount when the procedure is invoked and what you may do with it while 
the procedure is running.

It has correctly been pointed out that you therefore can't make an 
assumption about what exactly a const AnsiString parameter will do; you 
just have to be prepared in either case, and if it turns out to be by 
reference, don't modify the instance via another reference.

I simply propose constref (existing) and constval (hyptothetical) for 
those who come across situations where more precise programming would be 
desired.

--- Implementation ---
I had a few ideas about implementation of constval, as I described it, 
for AnsiString. (Or, alternatively, a way to change the behavior of 
const, though this is no longer what I advocate.) These are all 
speculative. These are some ideas, basically, not assertions. Also my 
knowledge of how FPC works is limited as I've said before.

1. It seems that if a string is a (non-const) local variable it should 
be safe. I base this on the following reasoning:

a) In order to trigger the undesired behavior, you have to get an 
instance with a refcount of 1 which actually has more than one reference 
to it. The only way to do this is to pass a reference to an instance 
with a refcount of 1 to a function accepting a const AnsiString 
parameter. (Aside: The critical value is 1 because that determines 
whether copy-on-write happens and whether it gets freed the next time 
the refcount is decremented.)
b) Furthermore, you must be able to access the non-const reference at a 
higher scope (object, class, or global).
c) To do this, you could either have a higher-scope variable which you 
assign to a local variable, or vice versa.
d) If you do either of these, the refcount becomes 2 and the problem 
cannot occur.
e) The problem cannot be triggered passing a local variable.

2. Implementing 1 would require that the reference count update can be 
applied or not applied to a specific function depending how it's called. 
This could be done in two ways I'm thinking of:
a) Move the responsibility for updating the refcount to the caller. 
There are pros and cons to this idea. It could result in slightly larger 
code (because the refcount update and try-finally are in more places). 
However I think it could also speed things up *even more than the 
current implementation* because the refcount updates for several 
non-const strings could be combined into a single try-finally in the 
caller, rather than having one in each function.
b) Another possibility is to have two entry points to the function. The 
update of the refcount and try-finally would remain in the function, not 
the caller. However the caller could enter the function at either of two 
entry points. One would do the refcount update and set up the 
try-finally, whereas the other would skip to the code after that. I 
don't know if this is even possible. It seemed like something that might 
be doable with some tweaking when I was looking at the assembly code.



More information about the fpc-devel mailing list