Providing implicit conversion of - memory-safety
bachmeier
no at spam.net
Tue Jan 23 21:18:53 UTC 2024
On Tuesday, 23 January 2024 at 19:27:26 UTC, Renato wrote:
>> Here's a reduced version of one of the most bizarre bugs I've
>> dealt with in any language. The only reason I didn't move on
>> to another language was because I was too busy at the time.
>>
>> The code allows for initial values if the index is less than
>> 0, otherwise it returns the element.
>>
>> ```
>> import std;
>>
>> double value(T)(T index, double * x) {
>> if (index - 5 < 0) {
>> return 0.0;
>> } else {
>> return x[index-5];
>> }
>> }
>>
>> void main() {
>> double[] v = [1.1, 2.2, 3.3];
>> // Works
>> writeln(value(3, v.ptr));
>> // Lucky: program segfaults
>> writeln(value(v.length, v.ptr));
>> }
>> ```
>>
>> I noticed this behavior only because the program crashes. Once
>> I figured out what was going on, I realized that the thousands
>> of lines of code I had already written needed to be checked
>> and possibly rewritten. If only I had a compiler to do that
>> for me.
>
> This code seems to be doing everything it can to run into
> undefined behaviour, though?
>
> Why is `index` of a type T that has no requirements at all
> (when the implementation quite clearly wants `size_t`, or at
> least an unsigned numerical value)? Why is it using a pointer
> for x when clearly you intend to use it as a slice? You
> probably have context that I don't, but I would never expect
> this sort of code to be anywhere near @safe :D
There are two things things that cause the problem. One is the
use of a template and the other is passing an unsigned type. The
reason the first parameter uses a template is because there are a
lot of types I could send as the first argument, and for some of
them there was a transformation of index (for instance, you can
pass a date as a long[2], or you can pass another type and pull
out the length, that sort of thing). It's using a pointer because
I was working with a C library, and that's how the data is stored
and passed around.
The data is time series. If after the transformations the index
is less than zero, it returns 0.0, which is used for all
pre-sample values. If it's non-negative, return the element at
that position.
One of the nice things about D is the ability to write this kind
of code in such a natural and (I thought) intuitive style. I
really like the way all this comes together. There's really no
way that code should have been able to do anything wrong. What's
terribly frustrating is that the compiler had full knowledge of
what was happening, but by choice it didn't say anything, even
though D is supposed to prevent these things that happen in C.
More information about the Digitalmars-d-learn
mailing list