[fpc-pascal] FPC 2.6.2 throws SEGV in fpc_AnsiStr_Decr_Ref(). How is this possible?

Bruce Tulloch pascal at causal.com
Fri May 10 03:19:33 CEST 2013


> The compiler turns such functions into procedures with an implicit
var-parameter
> and the *caller* passes the location where the function result should go
via that
> parameter.

Okay, thanks, that clarifies, now I understand how a variable in the
caller's scope can be affected while making assignments to Result in the
callee's scope BEFORE callee has finished executing.

Another way of stating this is; Result is a local variable of a function,
initialized to nil and passed by value to the caller upon completion ONLY
if Result not a reference to a dynamic type, otherwise it's an implicit var
argument with scope beyond that of the function.

Is that correct? If so, it would seem to be a bit of semantic trap for the
unwary :-)

> Such optimizations only occur in safe situations (e.g., not when
assigning to a
> global variable...

Does the compiler consider ANY non-local variable to be global?

For example, fields of an object?

> So you are probably writing in two threads to whatever you are assigning
the
> result of that function to.

Yep, makes sense, we will look carefully to see if that's what we're doing.

The functions concerned are actually methods of the TBlockSocket class of
the synapse library. We use an instance of this class in two threads; one
sending, the other receiving.

These threads have full shared memory protection in our own code but having
a look at the TBlockSocket implementation I can see at least one suspect;
FLastErrorDesc.

This field is changed by methods that send and receive on the socket which
means it's assigned values in the context of two different threads (given
our usage). Indeed it suggests TBlockSocket is not thread safe as currently
coded. Looks like a smoking gun to me.

Thanks one and all for all your helpful feedback!

Bruce.



On Thu, May 9, 2013 at 10:55 PM, Jonas Maebe <jonas.maebe at elis.ugent.be>wrote:

>
> On 09 May 2013, at 14:39, Bruce Tulloch wrote:
>
> > Thanks José, I can see that might cause a problem given bar passes result
> > by reference to foo without initializing result first. My question to
> Jonas
> > or others more knowledgeable than me about what the compiler does, is
> > whether result (in your example and my own case) is guaranteed to be
> > initialized to nil when it first appears in scope (i.e. before it's been
> > assigned any value in our code).
>
> Every instance of an automated type, whether it was explicitly declared or
> implicitly created as a temp, initially gets the value "nil".
>
> However, as Michael and Ludo explained, the "result" variable of a
> function returning an ansistring/unicodestring is not created inside that
> function itself. The compiler turns such functions into procedures with an
> implicit var-parameter and the *caller* passes the location where the
> function result should go via that parameter. This location can be a
> temporary location, but the compiler can also optimize this by directly
> passing the location of the variable to which you assign the result of that
> function call. Such optimizations only occur in safe situations (e.g., not
> when assigning to a global variable, because otherwise assigning something
> to the function result would immediately change the value of that global
> variable too), but as Ludo explains this means that you are looking in the
> wrong place for the data race.
>
> So you are probably writing in two threads to whatever you are assigning
> the result of that function to.
>
>
> Jonas_______________________________________________
> fpc-pascal maillist  -  fpc-pascal at lists.freepascal.org
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20130510/978942c2/attachment.html>


More information about the fpc-pascal mailing list