C++ Logo

liaison

Advanced search

Re: [wg14/wg21 liaison] (SC22WG14.18841) [Fwd: sudo buffer overlow]

From: Uecker, Martin <Martin.Uecker_at_[hidden]>
Date: Sat, 30 Jan 2021 22:27:22 +0000
Am Samstag, den 30.01.2021, 20:51 +0000 schrieb Niall Douglas via Liaison:
> On 30/01/2021 17:47, Uecker, Martin wrote:
>
> > > I think the chances of C++ adopting VLAs are indistinguishable from
> > > zero. But C supporting a subset of C++ ranges (specifically, contiguous
> > > ranges), well that I can see plenty of WG21 support for, in principle at
> > > least.
> >
> > the only type I am missing in C is a wide function type similar
> > to std::function to call callable objects from other languages.
> > (In theory, function pointers in C could be wide but ABIs can
> > not changed.)
>
> That is indeed useful. However if C were to adopt C++ lambdas, that's
> 95% of you there (plus lambdas solve an absolute ton of other itches in
> C).

You still need the generic type. This is why
C++ has std::function, or?

> The only thing remaining would be some facility to erase a given
> capturing lambda instance into a corresponding non-lambda invocable
> instance with a call signature compatible with existing C ABIs, and
> you'd have what you want.

Maybe I do not understand what you are saying,
but this does not really work due to ABI issues.

This is why I think a new wide function
pointer is needed in C. A huge advantage would
be that we can use this type also for
interoperability with C++ and other languages.

> (Note the hand wave here that C lambdas would be but one form possible
> of "unknown invocable all I know of which is that I can invoke it with
> this specific C callable")

> > The wide pointers for arrays would be syntactic sugar
> > around variably-modified type, so nothing we need urgently.
>
> Well that depends on how you'd implement them I think. I, like most C++
> folk, dislike intensely any notion of runtime-varying type or size of
> type.

The problem is that if you want to really capture the concept
of a dynamically bounded array using the type system, you
automatically end up with runtime-varying types (i.e.
dependent types as they are called it type theory).

> I would be fairly certain that anything C adopts which involves
> runtime-varying type or size will never be supported in C++.
>
> And that might be fine from a C perspective, but I think you can get
> wide pointers for arrays etc exclusively using static types, or bounded
> reference types. And if you can, I think you should.

A generic wide pointer for arrays of type T with N dimensions
would internally look something like this:

struct {
  int dims[N];
  T* data;
};

You could do bounds checking and indexing with them.
(It gets even more powerful with strides, but let's
ignore this for now).


The VM types (that we already have in C!) are fundamentally
very similar:

T (*data)[dN]...[d1];

The difference is that we have explicit control where the
dimensions come from which makes them more powerful.
Consider the following prototype:

void transpose(int X, Y,
  double (*o)[X][Y],
  const double (*i)[Y][X]);

Here we can express (using the type system!) how the
dimensions if input and out array correspond to each
other. This is pretty cool I think.

Another example. Let's assume we add the missing
extension we need to store them in a struct:

struct foo {
 int X, Y, Z;
 double (*p)[.X][.Y];
 double (*q)[.Y][.Z];
};

This gives us fine-grained control over how we store
the dimensions (without any duplication or waste!)
and again directly expresses the relationships
between the types of p and q.

I agree we also might want to add a wide type.
Maybe something like this:

double (*p)[:][:][:];

which is then transformed by the compiler to

struct {
 int d[3];
 double (*p)[d[2]][d[1]][d[0]];
};


But this would just be syntactic sugar on top
of a more powerful framework which we already
have!


> > I am not sure what C++ does here we could adapt, you mention
> > span or ranges. But what would be the corresponding
> > C++ type for the following dynamic multi-dimensional array?
> >
> > double (*ten)[z][y[x] = malloc(sizeof *ten);
>
> > That would be mdspan (https://wg21.link/p0009).
>
> mdspan isn't in the standard yet. It's harder than it looks in fact,
> because there _may_ be a ton of stuff you'd really like the compiler to
> optimise aggressively for, if only you could provide enough hints and/or
> appropriate layout for say SIMD or GPU offload to be guaranteed chosen
> by the compiler, for some given mdspan configuration. People are still
> batting around non-mdspan, mdspan++, --mdspan, and other variations on
> the design.
>
> My personal suspicion is that we'll end up just choosing mdspan, but
> caution is appropriate given that WG21 previously did a suboptimal job
> with std::valarray, which is nowadays considered in the same category as
> std::vector<bool> - well intentioned, useful, but not fully thought through.

Well, the more you write all these issue the more I love
C's simple yet powerful VM types.

> Whilst I don't propose that C should implement Ranges a la C++, Python
> or Rust, I do think a bare minimum builtin primitive on top of which
> Ranges can be safely constructed would be fabulous. By which I mean that
> Sewell et al type proof of correctness would be possble. This is not
> something C++ currently can do, because the language knows nothing about
> string_view, span, mdspan etc, and so we cannot really prove that a
> program using these are correct.

You need a powerful type system to express properties
of the terms you want to prove something about.

If C++ rejects dependent types because C++ people "dislike" them
(as you said above), then your type system will remain limited in
what you could do with it. Of course, external tools could
always attach their own more powerful types to C++ terms, but
the C++ type system could not help.

>
> (Just so I am 100% being clear here, I'd really like C++ via C to gain
> the ability to spot when a string_view is used after its string's
> lifetime has ended. If C implemented a primitive on top of which C++
> could built lifetime checks such as those, we all win, and your sudo
> buffer overflow never again happens in newly written code)

I do not quite get the connection to life time.

I think Rust is pretty cool and we could take some
of these ideas and add them to C/C++.

Best,
Martin

Received on 2021-01-30 16:27:30