I'm going to talk about how to write C++
at safe for some definition of
safety and
um the general idea is um what what what
is safety what kind of safety are there
what do we need uh that's the first
quarter then I'm going to show you that
we've been creeping up on that uh for a
few decades it's part of the initial
aims of
C++ then I'm going to talk about how to
write good contemporary C++ under the
label of the C++ core guidelines and
then I'm going to talk about profiles
which is about how to guarantee uh
safety because guidelines and being
careful is not sufficient in all areas
um so one of the reasons there's so much
talk about uh safety is that uh parts of
the US government uh started going on
about safety which is quite reasonable
but uh they they're talking about the
whole Community which may or may not be
true and they're talking about the
mythical language
cc++ um which I have something to say
about anyway you can look it up this is
a serious concern that we have to deal
with on the other hand there's not no
reason to panic C++ is is doing well in
general thing I mean to measures noise
not usage but so these numbers doesn't
show precisely anything but it does show
that
uh maybe a billion or two people depend
on what we are doing so we better do it
well
well um so we we have to address the the
safety issue it's it's a real serious
problem I mean I I really don't want my
brakes not to work when I press it if I
had a car um and uh there there are
other things if you're in finances you
you don't want a uh a transaction to
disappear especially when it went if it
was going into your account and so um
there's a lot of aspects of this and uh
the interesting thing is that massive
Improvement really is uh is possible in
a lot of areas um one of my messages on
this talk is don't write c/
C++ uh write
C++ um we can do much much better than
some of the problems that has been
documented and um well if we we don't do
it somebody else will tell us what to do
and we'll like that even
less um so ignoring safety issues would
hurt the
community and offering guaranteed safety
will be in the best tradition of C++ so
this is actually an opportunity I mean
don't don't let
a a problem stop you from doing
something good so um the idea of
complete type and resources safety was
in C++ from the beginning uh simula was
one of the completely safe languages
except for the bugs I was pretty good at
breaking it um
but one thing that we know is
that we couldn't have complete safety um
with the hardware we had then and we
can't now for all languages and for all
uses but being careful doesn't scare so
we have to use judicious programming
techniques supported by Library enforced
by language rules and Analysis and um I
I wrote up a basic model for how to do
that a few years ago I actually
presented it here but not much happened
um we need it to be C++ that is there
shouldn't be restrictions on what we can
do um even though there might be
restrictions on how we do it and there
shouldn't be any decline in performance
uh this is C++ and actually some of the
techniques for writing safe codes
improve
performance um there I'm talking mostly
about what can be done by a compiler and
static checking because it is free or
actually gives improvements in
performance but of course you need range
checking to deal with things that cannot
be be dealt with with
statically and so basically I'm talking
about type and resource safety um and I
think this is pretty well defined every
object is access according to the type
with which it was defined that's type
safety uh and every object is properly
constructed and destroyed uh resource
safety uh you can manage resources that
way um if you don't initialize things
then you are breaking some rule and
every pointer either point to a valid
object or is a null pointer that's
memory safety um that's harder to
achieve but we can do it and a reference
through a pointer is not through the
null pointer that is we have to check
for null pointers before we go and D
reference these valid pointers um and
access
through a subscripted pointer is in
range that requires a runtime check and
I'll get get to that so basically this
is just what the rules require you read
the uh the standard and that's what it
requires read uh Dennis Rich's 45 page C
manual from 78 that's what it requires
it's just we haven't been doing it and
so the rules I'm putting forward here
are are more deduced than invented they
are deduced for what it takes to do what
on this slide and um enforcement rules
that I'm suggesting are mutually
dependent you can't just take one thing
out of context and expect to get a
easily specified benefit out of it uh
you you have to have a framework for
what you are doing to see what you are
planning to get out of it and um C++
still has to serve a wide variety of
uses in areas we have millions ions of
users and and billions of people relying
on us and one size doesn't fit all we
can't just say this is this is what
safety is everybody do it this way um
that that that doesn't quite work C++ is
also ass systems programming we um
manipulate Hardware in various ways we
use unusual Hardware that uh is is is
not known in the language specification
and we can't Outsource this uh to other
languages a lot of the so-called safe
languages Outsource all the lowlevel
stuff to CS
C++ so if we couldn't do it uh well
there would be C left uh and basically
but somebody has to do the dirty job
here and we can't break billions of
lines of existing code I say can't not
shouldn't because we can't if we try
people will use the old compilers they
will go to uh different subset they'll
just ignore us this this can't be done
uh and we can't upgrade the millions of
developers quickly it takes uh a long
time I keep bumping into people who
learned C++ from videos and books that
are 10 or 20 years old I mean it's
tragic but they could have it could have
been so much easier and the result could
have been so much better if they had up
to-date uh material teaching up toate
C++ but getting a whole Community like
this like this to move forward is much
harder than than most people IM uh
imagine okay these are
difficulties but we must improve and we
can so the challenge is is to describe
what we mean by type safe C+ plus use no
violations of the static type system no
resource leak if if a system leaks a
resource memory uh locks file handles
and such I I wouldn't consider it safe
because I can crash it with the
equivalent of a denial of service attack
or I could just be slobby and it crashes
when it runs out of resources so I'm
very keen on resource uh safety and this
is actually one of the things that came
into C++ on in the first two weeks and
uh we have to convince developers to do
this there's a lot of belief out there
that if you do grubby complicated
low-level stuff it must be
faster and furthermore I can write this
grubby low-level complicated stuff to
snow how smart I
am this does not work um we we have to
raise the level of of programming and
get this to work at scale I mean if I
have a class of students I can get them
to do what I tell them to because
otherwise they get a bad grade if you
are a manager you can get people to
write code the way you like it to
otherwise they don't get their pay rise
or they get fired but at scale we
actually have to convince people they
have to believe it's true and so that's
an important
thing and stability over decades matters
I mean the only reason people will
believe that the code they write today
will run in 10 years is that the code
that was written 10 years ago runs
today um and safety is not just type
safety
uh I think most of the areas I see are
logic eras I have seen a less than um
and equal where greater than was uh
expected and the cost was very
large uh and uh
if you if you want to prove that the
program does what exactly does you get a
a very restricted language uh there's
some Ada Ada code that goes in that
direction resource leaks I mentioned
that concurrency eras um we are doing a
lot of concurrency to be able to scale
our problems and such and we have to
make sure that this works you could
consider any uh concurrent error a type
violation
because the an object wasn't used in its
proper way but it's well worth
separating it out so that you can
analyze and address it directly uh
memory corruption we just have to
eliminate that uh type errors um if you
use low-level code with a lot of costs
and void stars and other um tricky stuff
like that void star star even worse um
we have to avoid that and timing errors
if
a response is needed in um
say uh 1.2 milliseconds then um that's
that's not if if if you are not on time
it's not good enough in a lot of
realtime control
applications and uh allocation on
predictability um there's aad on the on
the use of the free store in um in in
Flight software you cannot allocate
something after the engine starts and
you can't deallocate something at any
point because you might get
fragmentation and stuff like that this
means that separately managed chunk of
memories are very important in C++ all
the significant applications have
something on the side side where they
manage their memory themselves uh the
vector is the first and simplest example
we all using that it actually takes a
chunk of memory and manages it for you
uh and then termination eras I've dealt
with uh systems where termination is not
acceptable now if you have say 40,000
processes you have to take into account
that something will crash roughly every
day or at least every week and therefore
you can have a strategy that says well
if a processor has a problem just crash
it because we have written our software
to make it to work but what if there's
not such an extra thing what what if
you're not allowed to crash a friend of
mine pointed out that he was programming
um scuba controllers there's only one
processor in them uh no crashing is not
an option some Financial systems legally
you can't crash because you could lose a
transaction
and that's not allowed legal so um
there's many things here I'm sure you
could find another slide or half a slide
of examples of this kind of thing we
have to be able to say what is it we're
trying to do we're not trying to do
everything everywhere because that is
not necessary for a lot of people and
anyway it's not feasible on the scale
we're talking about so security is also
not memory safety there's been some
confusion in places between security and
um and and safety type safety type
safety is not security um I was at a
security uh course at uh Bell Labs many
many years ago the first class was
lockpicking the second class you are not
allowed to use your badge to get into
the building if I can get your computer
all your backup tapes uh all your memory
sticks I've got your stuff um spies
inside attacks um there's if you're a
large organization you have people that
can be bought
or idealistic for something that's not
the company's thing uh spear fishing
apparently works very well door ridling
if you try enough places people have not
done the right thing denial of service
SQL re injection uh corrupted input data
so if you want to attack something you
always attack the weakest link I was
told how do you avoid getting your car
stolen at new yor airport the answer is
park next to a nicer
car um so what I'm pointing out I'm
talking about type safety and memory
safety and things like that but don't
confuse it with security security is a
system property and the system involves
computers people storage areas physical
things lots of stuff I'm not talking
about all of that but remember it
somebody comes and and and screams
security because you could have a bug in
your
program uh languages are not
safe um like that thing of writing uh
less than instead of greater than such
and all safe general purpose languages
have Escape Clauses you have to access
Hardware resources you have to improve
efficiency of key abstractions doing a
safe link list implementation is very
very hard if you want it to be
verified safe I think we're up against
the haling problem but let let's say
it's just close to impossible so there
are things that we want to to do and we
have to use the techniques that um that
they're not verified it's safe and then
you have trusted uh code segments that
works those are trouble spots of course
but also libraries uh code written under
less strict rules you have to call
something how about the operating system
that's written in C um you can't verify
um the the operating system for that
reason it's far too
complicated and often the Escape Clause
is C++ so we can't just close all unsafe
areas um being safe where it matters
having it guaranteed where it matters
and preferably uh by default is is
really good and so pointing out that uh
you can't get absolute safety is not an
excuse for ignoring safety issues it is
an argument for focusing our efforts to
where we can actually make
progress um so I'm going back in
history um
one of the reasons I uh started with C++
was I wanted to deal with uh hardware
and I wanted to abstract from it so that
I could write better code and static
type safety was the idea I've been
written writing in languages that were
statically safe for a while including
simula which is the root of a lot of the
uh higher level stuff in C++ we had
classes uh
encapsulation
things like that um but it's an elusive
ideal uh because sometimes we need
progress sometimes we need better um
progress in what we understand sometimes
we need better uh Hardware so um
efficient use of Hardware that's where C
is manage complexity that's where simula
is and I've been trying to move us more
towards the simular area where where we
can afford it where we can do
it okay so when I started um if you
wanted to call a square
root uh you could crash the machine
square root of two would crash the
machine if you are lucky otherwise it
just give you a bad result the point was
that uh the compiler had forgotten that
you required a double and it wasn't
converted so one of the first things I
did was to make sure that such things
didn't crash uh since crashes are
considered a safety problem you could
say that I started on this right
away um actually it was very interesting
in the context of tightening up the
language today was that I got 10 years
of trouble out of that little fix I mean
even C today is is is like that but it
was controversial do do you mean I have
to look at the Declaration to see what
it means I can't just look at the code
that was an argument I heard a lot it's
incompatible so whenever people didn't
like C++ C classes whatever in the early
days they they pointed to oh it's
incompatible it's it's it's it's
different you haven't done your job
right well I couldn't uh get my type
safety without uh having an
incompatibility and one thing I've
learned is people when they want to not
use a language like C++ they pick
something and says oh it doesn't do that
today it is safety it's not
safe um okay anyway it was essential the
type checking overloading user defined
types consistent linking type safe
linking all of these things require that
the language supported argument checking
properly fine so sometimes you just have
to do it it's important and I think
we'll get to that again on uh safety
issues and basic idea was to represent
things in code and uh create uh
abstractions that you could use that Mak
your code um simpler and actually safer
Vector string file handle concurrent
task message cues da da unfortunately
they're not all standard today but most
of them are things take time I think if
we want to address safety we need
abstractions that support
that
notion and immutability came in early
um
const um I I felt I needed it I was
coming out of operating systems and
things like that and I knew that those
things that couldn't happen things that
I didn't want to happen if I had con
constant um actually what I really
wanted was read only and write only but
um I I talk to the Sea guys and they
would take con they wouldn't take read
only and write only we would have been
better off with that but
fine um basically you can
do leral constants and you can do
interfaces this way that way we get
better interfaces that's also something
that keeps going on uh
ra um this was in the first two weeks
have a Constructor that constructs the
object initializes the object
uh establishes the invariant of the
object uh if nothing else if you have
encapsulation you need it if you don't
have encapsulation you still need it to
be able to think about your code and
then when you are finished if it has
acquired uh resources you uh have to
give them back again otherwise you have
a resource leak uh any librarian can
tell you that that people will take out
books and they'll forget to give them
back again it's a sort of human nature
and uh we have to do these things at
scale so resource release has to be
automatic and U it was phrased rather
differently in those days because I
hadn't invented the terminology but
today we we have it and I hope um we all
using it uh examples of non-memory
resources I have there file handles
locks sockets shaders
like that okay so basically here is an
example of a resource leak this is naive
on safe code and I used to see it a lot
people open a file they
acquire the file the file handle they
use it and they get out again and code
is not actually that nice it's sometimes
two pages long and there's a return
statement or a long jump or a exception
in that use F and you never get to the F
close so we we we need
to not have such code all the compiler
sees all the analysis that we see all
that the programmer sees is that a fun
at a poter comes out of a function and
the manual says it has to be given back
to another function this this is not a
good code and it was a source of bugs
and so what we do is represent things
directly in code I talk about a resource
it should be in the code whoops did
I
H strange um out of order um anyway so
uh objectoriented programming came out
of similar well- defined interfaces
classes abstract based classes
overloading all that kind of stuff
that's um um ol yand Dal in the funny uh
cheer jacket and CH nugo in the uh the
other jacket he was the one that
invented inheritance and basically
objectoriented
programming and but where I lost a slide
that showed how to uh handle the file
handle thing obviously you create a file
handle class and it's Destructor uh
closes the file
um problem solved and uh we should just
do more of that so the evolution of the
language of course continued uh
templates allowed us to have compile uh
time selection of implement of
implementations and we finally got
Concepts so we have precisely defined
interfaces we really should use those um
consistently if I if I had a time
machine I would go back and tell me
about Concepts back in H
and we would have had much better
templates and I would have had an easier
time designing and implementing them uh
containers so that we don't have to
fiddle with arrays and pointers and it
enables range checking there's enough
information available to range check
containers and the major Implement
implementations have range checked uh
vectors unfortunately there's not a
standard for it and you can't just walk
up to a computer and without doing
anything else gets range checking that's
sad I think and relevant in the context
of safety and algorithms we had the
traditional HL begin end stuff and now
we can actually just sort the vector or
any container and that again means that
there's bugs you can't make like you
can't sort from end to begin or things
like that it gets simpler it gets
clearer and um safer and smart pointers
we can use but uh there's SP
pointers um so we have range for and
spans um the the loops the sea style
Loops there are sort of suspect um I
mean at this end really the number of
elements there um and uh you you can't
range check it because the from the
language point of you because there is
not enough information in the pointer to
be able to do range check
uh now we have
span that uh that knows the size we can
range checks where it's needed or it can
just do the whole thing like in that
example there I'll again point out that
Dennis Richie and I was discussing this
problem
back uh in the in the 0s and he wanted
fat pointers that was span uh so did I
but it took us some time to get it this
is not I mean if Dennis had they been in
control of C we would have had this 20
years
ago oh and here was the slide that had
disappeared I will put it in the right
place but basically you solve the
problem by having the appropriate
abstraction that does the appropriate
checks and releases the appropriate
resources fine better late than
never um okay so uh I wrote up the
ideals for C++ and
basically uh one of the first things is
no implicit violations of the static uh
type system um and uh those are quite a
few things there the point is this has
been documented for a while this when
I'm talking about safety and safer
things and higher level didn't start
yesterday it's in the best tradition of
the language and uh benefits comes from
using the language which well uh use the
facilities we're talking about here and
avoid uh raw pointers that you're
supposed to delete an owning raw pointer
don't subscript the raw pointer because
you don't actually know what the range
is uh and don't de reference raw pointer
before you check whether it points to
something don't have uninitialized
variables it's a DFT uh and you can do
it uh that book there which I wrote for
beginners in
2001 I think it doesn't show any
pointers and arrays until chapter 17
after I show them how to do Graphics
this can be done the good C++ the higher
level C++ is a consistent set of
features you don't actually have to go
and Fiddle with the lowlevel stuff till
you really really need to you can write
perfectly good code perfectly good
applications without going down there
and so if you want um save C++ don't
write C C++ there's no such language but
there certainly are uses where you think
people had it they they say it's C++ and
they they do all the things I said on
the previous slides that you shouldn't
and uh they avoid the higher level stuff
usually claiming performance uh problems
and uh
it's they don't measure um I
teach sometimes graduate students and
they still don't know how to measure
stuff and they still talk about
efficiency this this shouldn't happen so
anyway we have to evolve our style
towards what's provably safe because
provably safe is the the the easiest
thing to deal with it's easiest things
to to to think
about and uh as usual I'm trying to talk
people into it uh it has its
limits so being careful doesn't scale we
have to formal formalize formulate the
rules for safe use uh we have to um
provide ways of verifying that people
actually do what they are trying to do I
mean I don't think anybody here I'm not
excluded that hasn't written a piece of
code and they thought it did something
and it
didn't I would say it happens uh
well probably every week to me um that's
why I like
compilers um and we have to articulate
the guidelines so that we can um so so
that we can understand what we're saying
long long lists of complicated rules or
Greek letters is actually not going to
be easy to follow um and then we have to
enforce the guidelines where needed for
what where where needed means we have to
say the this is what I want here in my
code we'll get to that so the State of
Affairs is that if essentially
everything what I describe in the past
and what I will describe in the right
rest of the talk has been tried and many
at scale for instance range checking
strings vectors and span but nowhere has
it all been integrated into a consistent
coherent whole and that's what I'm
arguing we should do um much of the work
uh is is
uh I'm talking to is influenced by the
work on the core guidelines what we have
to go further than the guidelines as I
said uh being careful uh
doesn't doesn't scale and the aim is
still guarantee type and resource safe
C++ and then other things too this type
and resource safe
is pretty fundamental but there's other
things we want
and therefore we have to specify what
these other things are and a lot of
stuff can be uh done today we don't have
to go and wait for a new release of the
standard or something like that and this
is not just about safety I have
seen code speed up by going to a higher
level by expressing more clearly what
should be done if I can understand
what's going to be happen What should be
done so can the optimizer and quite
often uh you get benefits one of my best
ways of uh debugging and speeding up
things these days is to rip out the
complicated stuff and uh what is left uh
the optimizer can do a good job
on
oops what is it
this okay uh C++ core
guidelines or just for information that
is the machine that that makes your
highend chips high-end processors
essentially all of them and of course
it's programmed in
C++ uh they contacted me to see if I
could help them hire good C++
programmers no I'm not in that business
but really good C++ programmers can do
really interesting things General
strategy um we rely on static analysis
to eliminate potential errors
and this is impossible for General code
it's easy enough to write a piece of
code that cannot be proven to be correct
and Global static analysis is just
unaffordable a scale so basically we
need rules to simplify what we are
writing to something that can be anal
analyzed uh efficiently and and cheaply
local static analysis and there are some
analyzers for um for the core guidelines
that does things like that and then
provide libraries to make relying on
these rules feasible if if we had to do
everything at the language level uh
things get slow and unpleasant to write
and then we won't do it with the right
abstractions with the right uh libraries
just about everything becomes um becomes
Pleasant okay there's a philosophy here
this is a slide I made I don't know
almost 10 years ago
I highlighted a few things in
red statically type
safe can be checked uh at compile time
don't leak resources prefer immutable
data all of this is safety related so
again this is in the best tradition of
C++ and raising the level of um of the
writing and then there's low-level rules
that we use to implement uh these ideal
so basically we State what we want and
then we make long lists of rules that
allows us to approximate getting that um
and that's the lowlevel
things um
yeah and the strategy of the uh core
guidelines and of the uh profiles that
I'm going to talk about next is the
observation simple subsetting doesn't
work if you want to subset C++ to
something safe or something elegant or
something whatever the first thing you
have to get rid of is subscripting raw
pointers and explicit memory management
without any implicit releases from
destructors well if you take that away
you can't build just about anything so
what you do instead is you build some
better abstraction
s uh vectors smart pointers uh file
handle classes things like that and once
that is done you can then cut away a lot
of the complicated and dangerous stuff
at the
bottom um this strategy seems to work we
use the STL the standard library of
course and then there's a small support
Library GSL that was by the way where um
where span came from and a lot of people
still use GSL span because it's
guaranteed range
checked and um but the point is we add
no new language features I want the
result of using all of this to be ISO
standard
C++ I don't want to design a new
language it's too hard work and it takes
too long I want to write code good code
now so what we want is C++ on steroid
uh not not some some pitiful
subset okay and so we can actually
um okay if I had 10 hours instead of one
and a bit I could go through this list
and argue that we can do all of that of
course there's not time to this this is
a key note not a deep technical dive so
we can eliminate on uninitialized
variable range errors n pointer D
referencing resource list and dangling
references we can do more things unions
use variants casts just don't do them
overloading and template programming
eliminates most cost if you do it right
underflow and o on overflow I have not
worked my myself uh on that there but I
showed you a picture of an engine
earlier there was a marine diesel engine
was so big that if you look carefully
you could see the engineer by cylinder
head number
five um and that is run by some generic
programming that checks for underflow
and overflow so it can be done uh I just
don't have specific proposal for it and
we have some uh ways of dealing with
data races but that takes a whole day at
least so that's it uh uninitialized
variables I mean just do it there's many
clever ways of having delayed
initialization that act like um like
initialization but the code becomes
brittle and it becomes hard for the
human to see uh what is going on even if
the compiler have no problems with it
making sure that every object is
probably initialized I'm in favor of
just initialize everything
there's one exceptional case at least
probably more which is a huge buffer and
if you're doing low latency stuff you
don't want to initialize the buffer
first and then fill it with good stuff
second then you've just doubled the time
for filling that buffer I can think of
quite a few Industries where you would
need to be able to have the Escape
Clause from the initialization rules
where you can Mark things this one it's
uninitialized so it stands out in the
code so you can check it and things like
that um a lot of these rules to become
realistic you have to have some kind of
Escape clause and you have to have it
explicit so that the humans and static
analyzers can understand what what is
going on um Range checking of course I
want range checking um I don't want
subscripting of individual pointers um
if if you are writing C style code you
should be horrified but uh we can do
without it uh vector and span are the
two main examples where the range
checking can be done and sometimes is
being done uh simply because there's a
sufficient information available to do
the check with a pointer that isn't we
have to trust that we have checked thing
the ranges
correctly and sometimes we don't get it
right so it's much better to to use the
abstraction for it range 4 is really
nice uh it eliminates a lot of the
static checking because you only have to
check the beginning and the end um
algorithms are good I had a bunch of
students do some measurements of Loops
uh two weeks ago they were really deeply
shocked uh for each and accumulate beat
their hand coated SE style
Loops uh no L but you should have seen
my
students okay and and rightfully so
they've been told low level stuff is
important and efficient so
often no point of T referencing uh it's
fairly easy to check that uh you you
have uh a unold pointer there's an
abstraction in the TSL there uh for it
or you could have the an static analyzer
check that there is a test close enough
to uh the um to to to to the use that
you can verify that it's been done uh
again I don't want analyzers to be allly
uh clever because I want to understand
it too uh no resource leaks be
consistent with uh using abstractions
that follow the
ra uh we have a whole bunch of them uh a
naked new is a code smill don't have it
a naked delete is uh the same don't have
it not an application code they belong
in implic applic in implementations of
abstractions and um I see a fair amount
of code like this uh mostly from people
coming in from U from java and C where
you have to say new uh to get a user um
to to get a
an object of a userdefined class so you
have a gadget there I don't know what's
inside the gadget it may grab locks it
may grab file handles and things like
that and then you write some code and
then you have to remember to delete it
delete it and people quite real says
well I don't want to have to write that
delete but they say I want my garbage
collector but the garbage collector is
not going to help you because of what
was inside the G you don't know what it
is uh it may be something that has to be
explicitly freed and that code of course
can either throw and get out not get to
the delete or it can uh return perfectly
ordinary stuff this is nothing to do
with exceptions uh though I love
exceptions and they're really good for
this kind of stuff you can get into the
trouble without having
that um and so re resource handles we uh
use a lot of unique pointers and the
shared pointers these days and that sort
of solves the problem uh we are now
guaranteed that the destructor is called
and things are properly released um
simple and cheap but but you know it's
still a pointer and it still uses the
free store there's allocations so what
really we should do is more uh local
objects U there everything works uh
without added notation and
added um added allocations of course if
you're writing code for a embedded
processor with very limited stack space
you have to be careful about this but in
in general programming and actually in
most programming this is what's
preferred so uh it's it's not just this
that should make you worried but you see
the uh the the make it new and analyzers
easily warn you against that but you
should also be a little bit suspicious
about the um the the smart pointers
because they're really
inelegant um okay so dangling pointers
you really have to eliminate dangling
pointers there's all kinds of bad things
that can be happen with a dangling
pointer you can write through it into
somebody else's memory you can read from
it and get some garbage data um
you you can scramble things this is
really bad and by pointer I mean
anything that directly refers to an uh
an object I mean this this could be a
smart pointer if you're allowed to them
to dangle it could be
references you name
it and we have to eliminate them we can
eliminate them with a combination of
rules and by assuming that raw pointers
are not owners so that we don't have to
get interference from the memory
management problems
here okay so here is a piece of code
that's not
okay uh it
looks
um innocent I get a pointer and I delete
it well under the rules I'm crafting
that is a naked new and the analyzer
will reject it and that is good because
when you see G it makes
something uh an object it passes it to F
and then it uses it the use down there
is a um is a use of a dangling pointer
and of course in a real piece of code uh
the void f ofx is not visible like that
it's probably on some Li Library
somewhere that you've never seen um and
but the static analyzers can can handle
this and should I I really would like
the guarantee that this doesn't happen
my code and what you do is you deal
with every object has one and only one
um owner that means that we know who's
who is supposed to do the deletes the
closings or whatever you call them and
then there can be as many pointers as
you like as long as they are
um
not in the execution after where the
owner uh was this is a fairly simple
simple model and uh it can be
enforced here is an example um I have a
function here uh that has a local
variable and I call G with the address
of
it um and uh G then stores it in a
global this has to be stopped we have to
analyze it and say that uh it's not okay
to take something that comes as an
argument and store it in something
Global because you don't know if it is
valid after uh you execute you you exit
um on the other hand things that we get
from from pointers actually uh pretty uh
good because under this rule they will
be valid when they come in into the
function and they will be valid until we
leave the function again because they
came from outside the
scope and
um what do we got here remember
containers um pointers or any anything
that point can be in containers so I
took here a vector of integers rest
something and that is okay we create
collections of pointers iterators
wherever we call them and give them some
functions to be called and then when the
function comes back again everything is
fine because the fact that they the
pointers were valid in the calling code
if here means that it's valid in the
called code we're fine we're not
actually having to eliminate all kinds
of uh stuff uh this this works on the
other hand it is not okay to return that
rest because there are point there to
local elements in it that will go out of
scope that will become invalid when we
uh
leave um invalidation can be a serious
problem so we need to eliminate it sorry
um here we have a traditional Vector use
push back of nine that can relocate all
the
elements fine that's uh that's usually
fine but G uses it in a not good way it
starts by grabbing a pointer to the
first element an iterator to the first
element then it calls the function that
does the push back and then it tries to
use the pointer it kept mean this is the
reason for using um reserve and for
using uh linked uh linked uh containers
like a list because things don't
relocate we can however
detect that this piece of code is is bad
um it has been done so what we actually
do we have the the idea of
invalidated uh when the pointer points
to an element of a container that may
have relocated the elements that called
invalidated it it may or may not be
valid and uh
then we can
uh handle it by a fairly simple
rule uh and no a const member
function uh doesn't
invalidate because it would have to do
something nasty to the const it would
have to use a um a cast or something
like that so also it's easily validated
by a an analyzer on the other hand we
must assume that
any um noncon member function could
invalidate it has access to the data and
it can it can it can it relocate it can
it can move things
around um I would think that we need a
new annotation in
the core guidelines and in uh the
profiles which basically says yeah this
one doesn't invalidate even though it is
non-const standard example Vector
operator subscript it doesn't
relocate um but it can't be constant so
uh it's also easily validated so that is
a provable thing so it is perfectly safe
and easy to do so uh represent ownership
we use ownership abstractions as usual
stay high level don't mess with the
lowlevel things if you don't but we
always have to consider how do we deal
with code that's not written according
to our rules like thing that like code
that has C style interfaces with lots of
point in them and so we have an
annotation in the uh core guidelines
primarily to deal with the fact that the
world isn't that simple and we don't own
it all um and that's called owner I can
say this poter is an owner I'm passing
it over to you and I know it's your job
to delete this thing can be done
um so basically there's been a fair
amount of work done with this um and
there's some rules about how you can
copy owners and not they they you can
deduce them from what is safe so I'm not
going to go through them here if you're
looking at the slides or you can freeze
this and see what this is so now I want
to get to uh future stuff where do we go
to here uh we can write good
C++ I hope I made a reasonable argument
for that and too many developers don't
they write c/ C++ this mythical language
uh guidelines are not enough we need
guarantees uh partly because we make
mistakes and uh partly because we're
more comfortable if we have a real proof
and uh we we we need new standards for
what the static analyzers what the
compilers analyze and so we have some
Alternatives of how we can proceed from
here to get the guarantees we we can
change
C++ uh we can start using another
language which is of course what
proponents of all other new languages
are suggesting and we can enforce a
variety of guidelines um that's the
profiles I'm arguing for so fixing
C++ how there is so many different or
and incompatible ideas about how to
change uh C++ and to change C C++ in
ways that addresses the problems I've
been talking to it will not look like
C++ and there are um several suggestions
so we have years of delay and chaos and
a single clean up language will provide
a single kind
of safety unless of course it adopts the
profile approach and uh that that would
not be what a lot of people people talk
about and the clean up C++ will have to
interoperate with classical C++ code
Forever that that's just just a fact is
these billions of lines of code are not
going to disappear and much of it is
critical much of it is really high
quality so gradual adoption is essential
partial adoption is
essential um
and well for C++ I have had had it's
meant to evolve but also meant to evolve
in a reasonable compatible way if you if
you accept that last statement it won't
won't be fixed in the way uh people talk
about and then we can try using another
language uh safety is used as an
argument uh often c/ C++ and very
typically ignoring c++'s strength and
very often uh ignoring weaknesses of
Alternatives um often the safety
mentions is just memory safety that's
not enough and the need for unsafe
construct is not heavily
featured and the need to interoperate
with other languages including C++ and C
tend not to be mentioned and the cost of
conversion can be ferocious that's
rarely mentioned and of course this is
natural this is human nature you you you
argue for your case and you
overestimate the virtues of what you
have and underestimate
the strength of the opposition but still
we have to be more serious about how we
um have these argument and we need to
get some numbers and anyway which other
language um the way I have seen it
argued we were going to have C++
replaced by about seven different
languages as of suggestions of about now
by the time it happens 40 years from now
uh we'll probably have 20 different ones
and they have to interoperate this is
going to be difficult anyway let's look
there's new languages new resources new
expert users every new language of
course is claimed to be simpler cleaner
safer and more productive than C++ on
the other hand we heard that one from
java at the time I said yeah if it
survives it will become three times
bigger and be better for it I was right
about that uh you can apply that
argument to most new
languages and uh often the claim
superiority is in a limited domain and
again often compared to c/
C++ and one thing I have noticed when
you have a new language this happened
with C++ also you get a bunch of writing
code they are just much better than
average they are much more enthusiastic
they're better informed uh they know all
the latest stuff and then you come up
against the law of large numbers when
you have a language that is used at a
large scale your developers are average
quality average enthusiasm Etc um which
means that number is comparing a small
new community with a large much older
community is is going to be
skewed um let's see um I was thinking
about what it would take to convert
something so said consider converting a
10 million line system there's lots of
those uh it needs High reliability and
high performance because if it wasn't
why would you bother converting it for
safety reasons and such a good developer
completes in lines of production quality
code today I don't know what n is it
depends on what kind of code we're
talking about but for the kind of
critical uh software we're talking about
now maybe 5
10 100 let's say 2,000 lines a year
that's not too far off and let's assume
that a 10 million line uh system can be
written in the new language in the new
way from scratch in 5 million lines
half the size um this is sort of very
optimistic but if this is true it'll
take 500 developers 5 years to complete
the new system and the old system will
have to be maintained by uh for those 5
years till you can replace it and so
what is the loaded salary of a good
developer that's the cost of the salary
uh Pension funds uh buildings heating
cooling Computing all of this kind of
stuff let's say half a million in the US
it's not that far off we can argue about
100,000 in each way but this thing so it
would
cost um roughly a billion added cost
over those five years and for 1 million
you can divide for 100 million you can
multiply um and I made the Assumption of
us
developers um if you can find a develop
because with the relevant
experience um in the new language that's
uh often a problem and maybe Outsourcing
could cut cost that doesn't always
happen when you Outsource and then it
has its own problems especially when the
um when you start talking security and
such it's it it it's not obvious how can
you can cut that course dramatically but
anyway um I I said that I assumed the
new system would half the size of the
old one it doesn't happen very uh very
often but it certainly is possible if
you have better understanding of the
problem better language better tooling
Etc such and there would be no feature
creep for 5 years this is hard and the
new system would be would work and be
delivered on
time uh what is is going on with this
stupid
system oh I see what went on with that
system I am not seeing what you are
seeing
now I
am okay uh so there are of course people
for whom a billion dollars or100
millionar or not a lot of money so let's
not just dismiss the whole thing for
that reason um there's people who think
that a 10 million uh line system is
medium I did some asking around here um
and
yeah and so I think I think these kind
of numbers are an argument for an
incremental and evolutionary approach uh
as opposed to just going to something
brand new and obviously that could be
C++ or a combination of C++ and other
languages that are able to interoperate
smoothly with C++ and you can have a
community of both things I think it's
better to stay with C++ anyway C++ will
play a major role for decades to come
and we have to keep working on it
standards committee has to focus and
make C++ better and then I was um
looking up something I knew and to find
a quote people like quotes so there's
something that's called G gals law a
complex system that works is invariably
found to have evolved from a simple
system that
worked in other words this idea of just
building the new system over on the side
without any of the problems of the old
one is a f fantasy but it's a very
popular fantasy um I I agree with that
last statement down
there so profiles how can we guarantee
safety with standard C++ code uh
guidelines are not enough and the
profile summary here um is that
everything is ISO C++ standard um the
fundamental guarantees is up uh the most
fundamental guarantee that we want is
complete uh type and resource safety
ownership has to con uh constitute a dag
otherwise the uh the model breaks down
if you have loops and such you can
handle loops with say shared pointers
and weak pointers but to easy proof uh
stick to a dag pointers dealt with as I
said before um gradual conversion
uh offering guarantees has to be
supported uh the set of guarantees are
open I do not
know whatever everybody wants for
guarantees I can see somebody wanting a
um unsafe guarantee where they can use
all the unsafe features in the latest
Optimizer um in in other words it's an
open
set and we want some fundamental
guarantees to be standard I I'm
imagining type and resource safety
memory safety range safety um arithmetic
safety things like that could be
standardized um nothing is easy to
standardize but this is possible and the
set of guarantees assumed are stated in
code otherwise we don't know which kind
of analysis to apply to a code and we
don't know if we're users what kind of
analysis the wor applied for that code
and there's many Notions of safety I've
said this before but I think it's worth
showing the the list again because
people tend to forget it and focus on
the thing that they're looking at just
now in in their everyday problems um and
here's the type and resource safety
definition basically every object is
accessed according to the type with
which it was defined boom that's a nice
one and we don't have any um any
leaks and so what about c/
C++ well it's not a language but I think
it's a style of usage that I happen not
to like it's probably also unavoidable
because you have to call C libraries and
then we have to think about how to call
things with other guarantees the owner
annotation and not all checking is
examples of that we can't just focus on
making the the new shiny version of
everything um it's too complex for
static analysis if we can write
arbitrary code we we're up against
Dynamic linking cost and the holding
problem um arbitrary C++ focuses to deal
with low-level abstraction so we have to
raise the abstraction level to the point
where analysis is possible and
understanding by humans and we care
about performance and type and resource
safety so the idea is guarantees with
static analysis have coding rules to
make sure that the analysis is feasible
and have libraries to make it uh
reasonable to to write such code and the
profiles is a coherent set of guarantees
not just a set of unrelated tests and
the profile
um is then specified as a set of
guarantees and then implemented with a
set of rules that yields the uh
guarantee that we wanted and um I've had
people saying this is just too novel
it's too complicated it's too new what
we want is something simple and new this
shiny new language that you can Define
in 45 pages just like uh the first
version of c um I I don't don't believe
so um there's a vote there you you're
always supposed to not do something new
you're supposed to just put put some
kind of aade on something old I don't
believe this is feasible I think we have
to have an overall approach a general
approach each
individual techniques and feature has
been tried before many times and that's
good but for specific tasks and they are
not none of those solves all the
problems so a combined and coherent
approach is necessary
and profiles has to go beyond guidelines
because we want it
validated uh and we have to deal with
provide in code annotations and we have
to deal with mixing of uh profiles
different sets of guarantees in a in a
large system you can't imagine a million
lines of code that all follows exactly
the same rule uh and if you can I'll
just up the number to 10
million uh so we mix profiles and I
think we have to find the
tightest specification of when we uh can
use the non validated non- guaranteed
features we can't just say
uh this these 100,000 lines are not
checked that's not good enough it it is
good to have maybe the implementation of
the link list um two pages code have
that
specified so that's just some design
work going here um still under
development I'm suggesting uh that you
have module based
controls memory safety here type safety
is suggested and incode controls
suppress type safety in this area and
enforce type safety in this area I could
have a piece of code that is just
too compc at or too difficult to convert
so I can't do it but I can say for this
section here I would like the analysis
to be done and suggest standard profiles
type safety range arithmetic uh would be
a good initial set and uh here's a
summary of what it would take to do this
in terms of uh
syntax and um this work in progress
there's Papers written about it and uh
you you can go and look it up there's
also talks about it and basically no
we're not here yet we've come a long
long way from classic C and from CW
classes and from C++ 11 and we have to
first of all get people who are not up
to date with C++ uh to become up to date
it does not mean using every new feature
exclusively and using every uh every
neat little new thing no it means uh
defining what you want and seeing the
simplest way of getting it the core
guidelines are an attempt with that and
we need to start standardizing uh
profiles as
described and um of course this is
something that uh can't be done by one
or two people maybe it could in five
years but I don't think we have five
years so how can you help um how do we
refine profiles what profiles do we need
uh how do we best formalize the
specification of a profile and what can
we do now I'm dreaming of something like
profiles light that uh
provides most of the guarantee of a
profile but can't do all the last things
because say the static analyzer isn't up
to it
yet and U what library compon components
can be simplified to use I've been using
a din array uh that doesn't have push
back so that I can use it in a
concurrent system without worrying that
somebody does a push back or on the
other
thread U maybe we need more of that and
I'm setting up a GitHub
for where people can put uh suggestions
and where I'm going to put my uh drafts
and S such so that that we can create a
community working on getting this kind
of stuff done uh in a reasonable time uh
the GitHub is
not live but should become live this
afternoon okay thank
you
um do we have questions do we have time
for questions or have a run over so
badly as we
can't that's if you have a question
please come up to the
microphone
there's one over there
also hey thanks a lot so you mentioned
uh for example uh Vector without push
back in a certain profile so uh do you
think that a profile uh will like
eliminate member functions in some cases
or just make those member functions
behave
differently I don't quite understand the
question sorry you mentioned that in a
certain uh context you might want a
vector class that doesn't have push back
yes so there could be a profile that
like eliminates certain member
functions um that's one way of doing it
that's not the way I imagined doing it
because well I did it some other way uh
because I couldn't actually mess with
our standard implementation of the
um of the vector so for instance my
students get a range check Vector I
can't do that without messing with the
implementation and there several
implementation so I don't do that
similarly what I did in case of the uh
invalidation was I used another class
which I call Din array which I believe
you can find in the GSL which simply
didn't have that operation that's the
other way of doing it and if you are not
uh the standards committee or a vendor
of a standard Library that's the way you
must do it and so I
did okay question on uh immutable data
you said prefer immutable data over
mutable data at the same time famously
the string class and C++ is
mutable and ISO quite you know some some
discussion about immutable string class
but it didn't really catch on um I hear
a lot about immutable string classes but
you know I like the mut mutating some
strings some of the time and uh I have
not seen a coherent argument for why
it's better to have it
deed uh immutable what are the benefits
what are the problems and in the absence
of such a suggestion we're not going to
get one furthermore there's so so much
code out there so it would almost
certainly be an example of a a different
thing um that was immutable but somebody
has to do a thorough logical and
hopefully data argument for why
immutable strings are good is it a issue
of correctness is it an issue of
performance all of that I haven't seen
that kind of argument thank
you
I noticed uh a lot of the various
suggestions you're making are enforced
by Static analyzers or are tooling
separately from the compiler one of the
issues I've observed when setting up new
C++ projects on my own or at work is
getting additional tooling into the
build chain into the CI takes effort and
is not trivial effort at production
scale do you have any suggestions on how
to make that process easier of how to
make you know tooling integration
simpler there there are couple of
problems related to Tool chains and yes
it's hard to get something new into the
tool chains and the usual problem with
C++ is that we have many of something we
we never just it's not that C++ doesn't
have a Graphic system it has many
graphic systems we have many build
systems we have many static analyzing
systems um so what I am hoping is that
the profiles will encourage people to
have to to build static analyzers that
supports a
specific
profile and that the build system the
compilation system sees that this is
required and uses the
installed um static
analyzer now a lot of what I'm doing can
actually be put into the compiler itself
because compiler is a static analyzer
and these days quite a sophisticated
stat static analyzer um the simplest
would be the in init no uninitialized
data rule which they're already doing
more complicated stuff to detect whether
it's been an uh initialized or
not but I think the the idea of profile
annotations should help with that
problem
thanks so it seems that the new
Improvement on safety and C++ are adding
or addition to the language new
annotations new types do you think and
there will be a time where the default
is actually um the saf ones and unsafety
one you actually need
addition uh if you want to maintain
compatibility you have to work through
extensions and to you
cannot efficient effectively eliminate
features from the language we tried
several times with deprecations and such
and E
even incompatible changes have caused a
lot of grief so I'm not going that way
what I actually am going for is to to
simplify the use of the language through
the gu guidelines and then if you follow
the guidelines you have a simpler
language to deal with you don't actually
have to know uh the horrors of pointers
to pointers to void uh because the
analyzer will stop you from writing one
um and so extend the language make a a
simpler subset of the language that you
can
enforce thank
you
uh hi uh you briefly mentioned about uh
you wanted to add right only when when
you were talking about con uh as the
language feature uh you mentioned that
it will create a better interface or
something like that so what were you
thinking of a use case of right only and
then uh is there alternative we can use
or uh yeah anything about right only I'm
afraid I didn't understand that oh uh so
when you were mentioning about the const
you talked about read only and write
only and then it would it would have
created a better interface if there was
write only like
const
um the const example was just an example
of how from the very earliest days um we
have tried to create a a safer language
a language where it's harder to make
mistakes and easier to understand and
and I just threw in a historical fact
that I didn't just actually have
const which is read only uh I also had
write only but uh I couldn't get it okay
all right thank
you hello um so do you
think um like sometimes you might want
to express that the function is thread
safe or that it does IO operations you
think maybe under the hood uh you could
use Tag dispatching uh to implement the
profile you were talking
about um I have not thought about this
so this is an off the cough
comment but yes I could imagine there
being a a threat safe annotation that
would that may be part of a profile
uh profiles will
invariably partly be built out of other
profiles currently in the um in the core
guidelines we
have
um memory safety and type safety and I
think there's three of them that would
add up to type and resource safety and I
would
imagine that a threat
safe
[Music]
um thread would be part of a profile
what I really would not like to see is a
total sort of 50 or 100 things you can
request because then you got chaos and
if you go and see the current static
analyzers they are very prone to giving
you a free
choice and that very often doesn't add
up to a coherent set so of guarantees so
yes it would be a candidate for
something but I'm not quite sure
what do you think that if we had the
compil time reflection as part of the
language we would be able to implement
most of the static analysis checks by
using Concepts or Conex functions
instead of a external
analysers no I don't think so it's a IT
addresses I would like to see static
reflection but I think it addresses
different uh sets of
problems yeah thank you for the talk um
I think there is a good examples when
you're in a controlled environment when
you are the author of The Cod but what
if how what do you think how you can
improve the safety when you're dealing
with the libraries that you know cc++
libraries that passing your pointers
what can be done there that is the
problem which I refer to as mixing
profiles you
can you can annotate the import or the
include um with something about what
assumptions you may make about uh what
you're importing and that's about all
you can do you can handle
subsetting of profiles
arbitrary you can sub setting and
disjoint what sort of arbitrary sets of
guarantees are just too hard to um
mechanically deal with and so we'll have
to have some annotations and have some
humans uh actually try and understand
and see what they're dealing with okay
and the problem will not go away yeah
for decades basically if you have
Rangers you it's you you we have to know
it's a problem we have to try and deal
with it as best we can but we can't
eliminate it thank
you hi um so I noticed that you
mentioned Concept in your talk and uh we
try to use it in our batteries at work
um I guess the problem we have is that
it's making the code become more complex
and understanding for other people when
they F to maintain appies and we haven't
found any actual benefit of using
concept um so I wonder if you can
elaborate on the benefits of it and um
some resource for gight to use it
correctly sure I mean I have used it
successfully in code that are not sort
of Computer Sciences especially
communication
software and we found it uh very helpful
uh one thing to avoid is people using
requires Clauses as um requires requires
and sort of low-level uses of guarantees
that creates a filthy mess I don't know
if that's what you did but that's one
thing I have seen uh failing people
think they're using uh modules they're
not they're using the assembly code for
creating
modules and well it's say successful as
a sampler
um and it takes some experience to build
proper Concepts um I've seen people try
and build Concepts on the idea that they
have to be the absolute minimal
constraints for everything uh again you
get far too many Concepts and you can't
remember them um when I write about
Concepts speaks about Concepts to say
concepts has to be designed to
um to to encourage comp uh composition
that is they have to be sufficiently
high level that a concept can be used in
many places in many algorithms so if
people build a um a less than concept
and somebody else uses a less than an
equals concept you you're on the way to
something chaotic whereas if you build a
um ordering Concepts as there is in the
standard uh then with all the four
operations
you're you're on the way to something
better uh I I mean it may be that
your problem area has something that we
haven't addressed uh but in most cases I
have seen problems like that it has been
been uh immaturity of uh of use it's
like when when people start writing code
they don't write good code uh they they
they make beginners mistakes
and I hope you don't think I'm rude when
I suggest that that might be a
possibility um if you analyze your stuff
and see if you can be precise about what
it was it didn't seem to work I would
like to hear about
it thank you yeah thank you and I think
this is it thank
you