On 19/04/2021 23:37, Niklas Holsti wrote:> On 2021-04-19 22:47, Paul Rubin wrote: >> Dimiter_Popoff <dp@tgi-sci.com> writes: >>> On 4/19/2021 14:04, Niklas Holsti wrote: >>>> ...their HR departments say that they cannot find programmers trained >>>> in Ada. Bah, a competent programmer will pick up the core concepts >>>> quickly, says I. >>> >>> This is valid not just for ADA. An experienced programmer will need days >>> to adjust to this or that language. I guess most if not all of us have >>> been through it. >> >> No it's much worse than that. First of all some languages are really >> different and take considerable conceptual adjustment: it took me quite >> a while as a C and Python programmer to become anywhere near clueful >> about Haskell. But understanding Haskell then demystified parts of C++ >> that had made no sense to me at all. > > > I agree that it takes a mental leap to go from an imperative language to > a functional languge, or to a logic-programming / declarative language. > > To maintain a Haskell program, one would certainly prefer to hire a > programmer experienced in functional programming, over one experienced > only in C, C++ or Ada.Certainly. The differences between C++ and Ada are much smaller than to Haskell. Some languages mix imperative and functional paradigms. In C++, you can do a certain amount of functional-style coding - you have lambdas, and with templates and generic functions you can manipulate functions to some extent. Ranges and list comprehensions are new to the latest standard, though being library features they are not as neat in syntax as you get in languages that support these directly (like Python or, more obviously, Haskell). Pattern matching is on its way too. You see at least some functional programming features on many interpreted languages too, like Python and Javascript. Going the other way, you get ocaml that is basically a functional programming language with some imperative features added on. But for someone unused to functional programming, Haskell does look quite bizarre. (Though it is not at the level of APL!).> >> Secondly, being competent in a language now means far more than the >> language itself. There is also a culture and a code corpus out there >> which also have to be assimilated for each language. E.g. Ruby is a >> very simple language, but coming up to speed as a Ruby developer means >> getting used to a decade of Rails hacks, ORM internals, 100's of "gems" >> (packages) scattered over 100s of Github repositories, etc. It's the >> same way with Javascript and the NPM universe plus whatever >> framework-of-the-week your project is using. Python is not yet that >> bad, because it traditionally had a "batteries included" ethic that >> tried to standardize more useful functions than other languages did, but >> it seems to have given up on that in the past few years. > > > Relying on libraries/packages from the Internet is also a huge > vulnerability. Not long ago a large part of the world's programs in one > of these languages (unfortunately I forget which -- it was reported on > comp.risks) suddenly stopped working because they all depended on > real-time download of a small library package from a certain repository, > where the maintainer of that package had quarreled with the repository > owner/provider and had removed the package. Boom... Fortunately it was a > very small piece of SW and was easily replaced. >Would that have been a Javascript library? It is common (mad, but common) to pull these from external servers (rather than your own webserver), and it would happen every time a webpage with the code is loaded.> The next step is for a malicious actor to replace some such package with > malware... the programs which use it will seem to go on working, but may > not do what they are supposed to do.

C++, Ada, ...
Started by ●April 17, 2021
Reply by ●April 20, 20212021-04-20
Reply by ●April 20, 20212021-04-20
David Brown <david.brown@hesbynett.no> writes:> For the kinds of code I write - on small systems - I disable > exceptions in C++. I prefer to write code that doesn't go wrong > (unusual circumstances are just another kind of value), and the kind > of places where exceptions might be most useful don't turn up often.That's not so great if you call library routines that can raise exceptions, and having to propagate error values back up the call chain is precisely the hassle that exceptions avoid. There is a proposal for "deterministic exceptions" in C++ that work like Haskell's Either monad. I.e. they are syntax sugar for propagating error values upwards, with the compiler automatically inserting the tests so you don't have to manually check the return values everywhere. I guess they are a good idea but I don't know if they can replace the other kind of exceptions. I don't know the current state of the proposal but some info and links should be here: https://github.com/cplusplus/papers/issues/310
Reply by ●April 20, 20212021-04-20
On 19/04/2021 23:17, pozz wrote:> Il 19/04/2021 22:48, David Brown ha scritto: >> On 19/04/2021 18:38, pozz wrote: >> >>> What do you suggest for a poor C embedded developer that wants to try >>> C++ on the next project? >>> >>> I would use gcc on Cortex-M MCUs. >>> >> >> I'm not entirely sure what you are asking - "gcc on Cortex-M" is, I >> would say, the right answer if you are asking about tools. > > I mentioned the tools just as a starting point. I don't know almost > anything about C++, but I coded C for many years. I think there are some > precautions to take in this situation to learn C++ respect learing C++ > as the first language. > > >> Go straight to a new C++ standard - C++17.� (If you see anything that >> mentions C++98 or C++03, run away - it is pointless unless you have to >> maintain old code.)� Lots of things got a lot easier in C++11, and have >> improved since.� Unfortunately the law of backwards compatibility means >> old cruft still has to work, and is still there in language.� But that >> doesn't mean you have to use it. >> >> Go straight to a newer gcc - gcc 10 from GNU Arm Embedded.� The error >> messages are much better (or at least less horrendous), and the static >> checking is better.� Be generous with your warnings, and use a good IDE >> with syntax highlighting and basic checking in the editor. >> >> Disable exceptions and RTTI (-fno-exceptions -fno-rtti), and enable >> optimisation.� C++ (used well) results in massive and incomprehensible >> assembly unless you have at least -O1. >> >> Don't try and learn everything at once.� Some things, like rvalue >> references, are hard and rarely useful unless you are writing serious >> template libraries.� There are many features of C++ that are needed to >> write libraries rather than use them. >> >> Don't be afraid of templates - they are great. >> >> Be wary of the bigger parts of the C++ standard library - std::vector >> and std::unordered_map are very nice for PC programming, but are far too >> dynamic for small systems embedded programming.� (std::array, however, >> is extremely useful.� And I like std::optional.) >> >> Think about how the code might be implemented - if it seems that a >> feature or class could be implemented in reasonably efficient object >> code on a Cortex-M, then it probably will be.� If it looks like it will >> need dynamic memory, it probably does. > > Dynamic memory... is it possible to have a C++ project without using > heap at all? >Baring a few minor issues and easy tweaks, pretty much any C code will also be valid C++ code. Some people use C++ as ABC (A Better C), taking advantage of a few features like better constants, references (rather than pointers), namespaces, and other points that look like they could work as extensions to C rather than a new language. In general, you avoid dynamic memory in C++ by avoiding "new" or any standard library functions that might use it - just as you avoid "malloc" in C by not using it. There are many standard types and functions that can use dynamic memory in C++, but usually it is quite obvious if they will need it or not. When you want to be more sophisticated, C++ gives you features to override and control "new" and memory allocation in many ways, with memory pools and custom code. But don't try that in the first couple of days.
Reply by ●April 20, 20212021-04-20
On 20/04/2021 00:55, Paul Rubin wrote:>>> And keep smiling! [](){}(); (That's the C++11 smiley - when you >>> understand what it means, you're laughing!) > > Heh, if that means what I think it means. >If you think it means anything at all, then you are probably correct about what you think it means. (That sounds a bit cryptic, but it is meant literally.)
Reply by ●April 20, 20212021-04-20
On 20/04/2021 08:18, Paul Rubin wrote:> David Brown <david.brown@hesbynett.no> writes: >> For the kinds of code I write - on small systems - I disable >> exceptions in C++. I prefer to write code that doesn't go wrong >> (unusual circumstances are just another kind of value), and the kind >> of places where exceptions might be most useful don't turn up often. > > That's not so great if you call library routines that can raise > exceptions, and having to propagate error values back up the call chain > is precisely the hassle that exceptions avoid. >If you don't use exceptions, don't call library functions that raise exceptions. If you don't treat "errors" as something mysterious that might or might not happen, which should wander around the code in the vague hope that something somewhere can make it all better, then you don't need silent propagation of exceptions - also known as invisible and undocumented longjumps. When you are programming on a PC, you can be using huge libraries where you know the basic interface of the parts that you use, but have no idea of the contents and what might possibly go wrong. When you are programming for small-systems embedded systems, you /know/ what can go wrong in the functions you call - /nothing/. There are no unexpected or untreated errors - or your development is not finished yet. Any possible returns are part of the interface to the function, whether they are "success" returns or "failure" returns. In this kind of system, you don't have the option of showing a dialogue box to the user saying "unexpected exception encountered - press OK to quit".> There is a proposal for "deterministic exceptions" in C++ that work like > Haskell's Either monad. I.e. they are syntax sugar for propagating > error values upwards, with the compiler automatically inserting the > tests so you don't have to manually check the return values everywhere. > I guess they are a good idea but I don't know if they can replace the > other kind of exceptions. I don't know the current state of the > proposal but some info and links should be here: > > https://github.com/cplusplus/papers/issues/310 >They are indeed a good idea. I am quite happy with explicit exceptions or error indications that are part of the interface to functions, and I would be happy with syntactic sugar and efficient compiler support. What I would /not/ use on embedded systems is hidden mechanisms where you don't know what exceptions a function might throw. There are plenty of other attempts at conveniently and explicitly handling errors using templates and classes that typically work as sum types (like the "Either" you mentioned) or a product type (like a struct with a "valid" flag as well as the real result type). I have found it convenient to use std::optional, for example.
Reply by ●April 20, 20212021-04-20
On 2021-04-20 2:01, Paul Rubin wrote:> Niklas Holsti <niklas.holsti@tidorum.invalid> writes: >> You can impose that constraint if you want to: if I had defined >> type Zero_Handler is not null access procedure; >> then the above declaration of the At_Zero component would be illegal, >> and the compiler would insist on a non-null initial value. > > Oh, this is nice. > >> But IMO sometimes you need pointers that can be null, just as you >> sometimes need null values in a database. > > Preferable these days is to use a separate type for a value that is > nullable or optional, so failing to check for null gives a compile-time > type error. This is 't Option in ML, Maybe a in Haskell, and iirc > std::Optional<T> these days in C++.I'm not aware of proposals for such a thing in Ada.>> The state of the art in Ada implementations of critical systems is >> slowly becoming to use static analysis and proof tools to verify that >> no run-time check failures, such as accessing a null pointer, can >> happen. That is already fairly easy to do with the AdaCore tools >> (CodePeer, SPARK and others). Proving functional correctness still >> remains hard. > > I know about SPARK. Is CodePeer something along the same lines? Is it > available through GNU, or is it Adacore proprietary or what?CodePeer is a for-money AdaCore tool, a static analyzer that basically (AIUI) applies bottom-up weakest-precondition construction and pre-post-condition analysis to detect many kinds of logical programming problems, in particular possible failures of run-time checks. See https://www.adacore.com/codepeer. To use it in practice on larger programs, one usually has to guide and help its analysis by writing a certain amount of explicit precondition and postcondition aspects into the Ada source (which CodePeer then verifies as part of its analysis), but that has other benefits too, of course.> I still have Burns & Wellings' book on SPARK on the recommendation of > someone here. It looks good but has been in my want-to-read pile since > forever. One of these days.Note that most if not all of the SPARK-specific comments that were used earlier have now been superseded by the precondition, postcondition, invariant etc. aspects in standard Ada, and the SPARK tools have been updated accordingly. I'm not sure if this replacement is complete; I haven't used SPARK. By the way, did you know that NVIDIA has started using SPARK? There's a presentation at https://www.adacore.com/webinars/securing-future-of-embedded-software. niklas holsti tidorum fi . @ .
Reply by ●April 20, 20212021-04-20
On 19.4.21 21.33, Tom Gardner wrote:> On 19/04/21 17:38, pozz wrote: > >> What do you suggest for a poor C embedded developer that wants to try >> C++ on the next project? > > Choose a /very/ small project, and try to Get It Right (TM). > > When you think there might be a better set of implementation > cliches and design strategies, refactor bits of your code to > investigate them. > > Don't forget to use your favourite IDE to do the mechanics > of that refactoring.I'd like to add: Read the generated assembly code. C++ is prone to exlpode surprises into it. An experienced C embedded programmer would read the code, anyway ... -- -TV
Reply by ●April 20, 20212021-04-20
On 20/04/21 13:09, Tauno Voipio wrote:> On 19.4.21 21.33, Tom Gardner wrote: >> On 19/04/21 17:38, pozz wrote: >> >>> What do you suggest for a poor C embedded developer that wants to try C++ on >>> the next project? >> >> Choose a /very/ small project, and try to Get It Right (TM). >> >> When you think there might be a better set of implementation >> cliches and design strategies, refactor bits of your code to >> investigate them. >> >> Don't forget to use your favourite IDE to do the mechanics >> of that refactoring. > > I'd like to add: Read the generated assembly code. C++ is > prone to exlpode surprises into it. > > An experienced C embedded programmer would read the code, > anyway ...Agreed. Unfortunately I've come across too many interview candidates that haven't a clue about the code emitted by a compiler when it encounters a function call.
