Performance improvement to strnlen().

Václav Zeman vhaisman at gmail.com
Mon May 27 11:46:06 UTC 2013


On 27 May 2013 12:25, Adam Nowacki wrote:
> On 2013-05-27 10:37, Václav Zeman wrote:
>>
>> On 26 May 2013 21:01, Lee Thomas wrote:
>>>
>>> On 2013-05-26 08:00, Václav Zeman wrote:
>>>>
>>>>
>>>> On 05/25/2013 10:27 PM, Lee Thomas wrote:
>>>>>
>>>>>
>>>>> +       lp = (const unsigned long *)((uintptr_t)str & ~LONGPTR_MASK);
>>>>> +       va = (*lp - mask01);
>>>>> +       vb = ((~*lp) & mask80);
>>>>
>>>>
>>>> I do not think that this correct C. This is type punning violating the
>>>> rules of the language.
>>>
>>>
>>>
>>> Hello Václav,
>>>
>>> The aliasing here is safe, because there are no writes through either of
>>> the
>>> pointers, and the reads are correctly aligned.
>>
>> I disagree. IANALL but AFAIK, this is simply not allowed by the
>> language => UB => even though it seems to work in this instance, you
>> are just lucky the UB is actually doing what you expect.
>
>
> It is not possible to tell if the result would be undefined by looking at
> the strnlen function alone.
IMHO, it is possible to look at the strnlen() function code and see
the UB there. UB is is there even if it does not manifest itself to
you by producing executable that gives you unexpected results or that
crashes.

> Internally it doesn't break any aliasing rules
> as char and long are allowed to alias. UB can only happen when the input
> string was created with incompatible type (not char and not long) and the
> strnlen function got inlined.
No, you got it wrong here. You can access any type of object by char
pointer. However the reverse is not true.

> Preventing inlining would be sufficient to
> guarantee correctness in any case.
Preventing inlining is masking the problem but it does not make it go
away. Also, in these days when compilers can optimize across
translation units, you cannot be sure the UB will be masked even if no
inlining happens.

--
VZ


More information about the freebsd-hackers mailing list