back to article Carnegie-Mellon Uni emits 'don't be stupid' list for C++ developers

Carnegie-Mellon University's Software Engineering Institute has followed-up its secure C programming rules from last year with a similar set of standards for C++. In the institute's announcement on Wednesday, it says it has put ten years into researching secure coding. The resulting SEI CERT C++ Coding Standard has 83 rules …

  1. Destroy All Monsters Silver badge
    Windows

    So...

    Basically, we need an expert system to tell the developer when he might want to reconsider (best while writing code, otherwise in a post-processing step).

    Actually, these more or less exist, I hope people use them. OO-flavored pseudo-assembler is as nice as a glass jar of elephant's foot.

    1. jake Silver badge

      Re: So...

      Actually, hand-massaging of compiler output prior to assembling & linking is kind of fun, when you approach it with the right attitude. Jars of nuclear waste? Not so much.

      Disclaimer: I code in C and rarely touch the super-set clusterfuck known as C++ ...

      1. Anonymous Coward
        Anonymous Coward

        Re: So...

        Now now, jake,

        Good C style code, can be made a lot more efficient, using the more expressive C++ compilers, as an assembler man, I present you proof https://godbolt.org/g/uq6p8o

        If you've not had a play recently you might be surprised.

        Now if you were to complain about bootstrapping a minimal C++ runtime, compared to a minimal C runtime, fair point, but the language is a fine one, in capable hands.

        How's the greenhouse doing? I'd like my own slack powered farm one day, you make it sound a lot of fun.

    2. Robert Carnegie Silver badge

      The expert system should appear as an animated paperclip.

      Then everyone will be careful to never, ever risk summoning it.

  2. DrXym

    Good advice but

    Some of the advice is borderline farcical, not because the advice is wrong but because the language allows those things to be written in the first place.

    - Do not read uninitialized memory

    - Do not access an object outside of its lifetime

    - A lambda object must not outlive any of its reference captured objects

    - Do not rely on the value of a moved-from object

    - Use valid iterator ranges

    - etc.

    The list goes on and on.

    It's no wonder that Rust is gaining such interest. I'd say a very substantial percentage of these issues, would be stopped in their tracks by the design of the Rust language / library and by the compiler's lifetime / borrow checks without sacrificing any performance.

    1. gv
      Alert

      Re: Good advice but

      Good fun and interesting times can be had by doing the opposite of those rules.

      1. tiggity Silver badge

        Re: Good advice but

        Indeed, browsing through uninitialized memory can throw up all sorts of interesting information.....

    2. Ogi

      Re: Good advice but

      > Some of the advice is borderline farcical, not because the advice is wrong but because the language allows those things to be written in the first place.

      Any language flexible enough to give you full and total control over the machine is powerful enough to blow your foot off if used incorrectly.

      The concept of C (and C++ presumably) is that the language is your servant. You tell it exactly what to do, and it does it (as long as it is a valid instruction). It doesn't advise you, it doesn't question you, and it doesn't deny you the ability to do something.

      Of course, whether it does what you intended it to do, or goes off and kills a puppy, is an issue of programming ability and/or understanding the problem set you are trying to solve (and the constraints of the environment).

      Like most tools, there is a time and place for it. I am not going to whip up a quick C program to parse a text file, but likewise I am not going to write a kernel (or embedded code) in Python or Bash.

      I think it is a good thing that CERT has done this, like a "best practices" if you want to write more secure, less exploitable code. It is up to the end user whether to follow it, or whether they really need to access unallocated memory for some particular reason.

      No comment on Rust, because I haven't had a look at it myself, but have heard good things from people.

    3. Dan 55 Silver badge

      Re: Good advice but

      You say do not read uninitialized memory, I say that memory's mapped to hardware device so I don't need to initialise it.

      You say do not access an object outside of its lifetime, I say have you not heard of RAII?

      You say a lambda object must not outlive any of its reference captured objects, I say I know when to pass by value instead.

      You say do not rely on the value of a moved-from object, I say you don't need to because you've just used move from to quickly create a new object and can now use this object for something else without all the expensive object creation cost.

      You say use valid iterator ranges, I say there are iterators to do that. If you don't use them, that's your choice.

      You say C++ lets you shoot yourself in the foot, I say be clever enough not to aim at your foot in the first place.

      1. John Smith 19 Gold badge
        Unhappy

        "I say be clever enough not to aim at your foot in the first place."

        Which suggests you practice these rules (or things with equivalent effect) unconsciously

        These rules are not for you.

        They are for the people who don't do so, who need to be told this is a bad idea, before they do it.

        Of course whether they will bother to read these rules before they make an almighty clusterf**k (is core Windows still written in C++ ?) is another matter.

    4. Suricou Raven

      Re: Good advice but

      C is a powerful and dangerous language. The ability to manipulate memory at such a low level without any form of bounds checking makes it one of the fastest languages around - which is why C and C++ remain the language of choice for any situation where performance is absolutely critical.

      1. Claptrap314 Silver badge

        Re: Good advice but

        BS. I spent eight years in asm because that was the only language that could handle the problem I was addressing. Going back up to C was astoundingly painful from a performance standpoint. MP computations without the carry bit? Here--let's just throw away half of our register size & reduce speed by a factor of four. Check for integer overflow? Let's see... Nope, that won't work. Naw, that won't either. Good thing I spent a lot of time working with registers--I would hate to think what would happen if someone without such experience tried this!

        For absolutely critical performance, you want access to the parts of the instruction set that C denies you.

        1. John Smith 19 Gold badge
          Unhappy

          "For absolutely critical performance,..access to the...instruction set that C denies you."

          I see, you don't use a profiler so can't spot where the 5% that actually matters is being executed.

      2. david 12 Silver badge

        Re: Good advice but

        >one of the fastest languages around<

        Compared to LISP, the other language CS majors were being taught in the 80's.

        On the other hand, Pascal and FORTRAN were always faster and lighter than C, (C99 and C11 and C++ made significant changes to partially address the gap), which is why C in particular was never used for any situation where performance was absolutely critical.

        "The ability to manipulate memory ... without any form of bounds checking", was of course, the least of the disadvantages of C & C++. Once you get outside debug builds, all languages allow compilation without bounds checking.

        1. Ken Hagan Gold badge

          Re: Good advice but

          "Pascal and FORTRAN were [in the 80s] always faster and lighter than C"

          Just to elaborate, for the benefit of the down-voters who are clearly in need of a history lesson...

          Fortran explicitly allows (and has always done so) the compiler to assume that arguments (which are traditionally passed by reference) are not aliases of each other. C has never had such rules and there is plenty of code out there that would be broken by such. With no aliasing, the Fortran compiler has optimisation opportunities that the C compiler does not have.

          This is particularly significant in numeric code, where passing two or more arrays of numbers is an extremely common thing. Consequently, C has always struggled to match Fortran's performance in this area. In mitigation, most C compilers have compiler options or pragmas to let you relax the aliasing rules in particular cases, but obviously that takes you beyond the standard language.

          On the other hand, these days it is less of an advantage because the fastest code is probably written in assembly language using SIMD instructions, or written for the GPGPU. Languages differ and times change.

          1. swm

            Re: Good advice but

            The original FORTRAN compiler competed with assembly code and most "real" programmers shunned FORTRAN until it could be demonstrated that it produced code as good as or better code as an experienced assembly language coder. This explains some of the bizarre rules for subscripts in FORTRAN I. The rules were designed to match the index and test instructions of the IBM 704. This is also why DO loops go through at least once. The three-way branch IF statement also matched the compare and skip instruction.

    5. bombastic bob Silver badge
      Devil

      Re: Good advice but

      not using (...) and not allowing unsigned integers to 'wrap' is short-sighted...

      the implications of 'printf'-like utilities, as well as gcc format checking pragma, were pointed out in the comments. But there are use cases for wrapping an unsigned integer, SUCH AS the calculation of a time interval on a 32-bit unsigned value that calculates milliseconds or microseconds, and wanting to schedule events based on elapsed time. When you EXPECT a wrap-around, you can code around it.

      example:

      uint32_t lTick = millis(); // # of milliseconds since start, using 32-bit unsigned value

      ...

      if((int32_t)(millis() - lTick)) > my_interval) { do something; lTick += my_interval; }

      this pretty much works universally, and is similar to what the Linux kernel does when scheduling things based on 'jiffies'.

      (and in some cases I'll even truncate the math down to 16-bits to make code work faster, such as on a microcontroller like Arduino, where this example might be used a LOT)

      so... maybe NO UNHANDLED unsigned integer wrapping?

      (yeah a FEATURE, not a bug - I like to work WITH the system's limitations, not against them)

      1. Richard 12 Silver badge

        Re: Good advice but

        Guidelines are there to make you think when you break them.

        Almost of of these recommended practices will have occasions when they should or indeed must be broken.

        - The classic "access uninitialised memory" reason is when the memory content in question comes from another device, whether by DMA or other means. Initialising it yourself would be a bug - but reading past where the DMA has currently reached is also a bug.

        So yes, break the guidelines - but when you do, think about why you're breaking them. Is it the right thing to do, or just the easy thing?

        1. barbara.hudson
          Unhappy

          Re: Good advice but

          Unfortunately, your point will be lost on the 99.9% of c programmers who never understood the use of, for example, the volatile keyword ...

  3. Anonymous Coward
    Anonymous Coward

    The document's also available as a wiki

    Be careful is you use the wiki "copy" as it's live and is a real pain to work with if you're using tools for automatic enforcement as they will enforce against a specific version.

  4. jake Silver badge

    Oh, goodie!

    Yet another C++ "How-To" book. That's just exactly what the world needs, judging by the dearth of such tomes on Uni bookshelves.

    1. Anonymous Coward
      Anonymous Coward

      Re: Oh, goodie!

      Most of the books that are out there show design patterns giving elegant solutions to common problems. There is very little out there to help stop you from accidentally writing code that contains instances of undefined behaviour.

      CERT C++ (and similar, e.g. MISRA C++) aim to try and eliminate such behaviour from code.

      1. Ken Hagan Gold badge

        Re: Oh, goodie!

        "There is very little out there to help stop you from accidentally writing code..."

        and a 435 page tome is not going to help with that one iota because unless the checking is automated it simply won't happen. No-one has the time and energy to check each line of new code against such a vast list.

        "Once established, these standards can be used as a metric to evaluate source code (using manual or automated processes)."

        As it happens, I already have a compiler that will test quite a number of these things in those cases where it can be checked at compile-time. (Modern compilers do pretty much everything that lint did 20 years ago.) The difficulty is that we still have all the undecidable cases left over and (as hinted by an earlier commentard) any sufficiently powerful language will allow undecidable cases.

        If CERT (or anyone else) has a magic wand that will point at those cases (with sufficiently few false positives that it is actually worth me reading the output and sufficiently many true positives that I can justify splashing the cash on the tool) then I'm all ears. They could prove the worth of their tool by pointing it at some of the millions of lines in popular FOSS projects and submitting bug reports for all the security problems *before* they are posted as 0-days. (And yes, some vendors have tried this, but the fact that everyone didn't immediately go "wow!" and buy their product suggests that the results weren't clear-cut. Perhaps all the low-hanging fruit in this area were eaten by lint when I was in short trousers and even the medium-height stuff has been picked off by language evolution since then.)

        1. Anonymous Coward
          Anonymous Coward

          Re: Oh, goodie!

          Coverity is decent.

          Sonar has little value to me over using Clang's static analyser, which is really rather good, combined with the usual suspects, compiling against different compilers / platforms, valgrind.

          Nothing else I've seen is worth the price or more importantly offers an advance on the open source tools.

          1. Paul Crawford Silver badge

            Re: Coverity is decent

            It is also available free to FOSS projects.

            While there are numerous warning that can be ignored, the golden rule for all such code-profiling tools is to make sure you understand the nature of the warning before you fix it or ignore it.

            Also worth a mention are some free (at least on Linux, maybe others?) memory checking tools like valgrind and the good old electric-fence library. While not checking your source code as such, they do help with detecting run-time memory errors such as double-free, leaks, etc.

    2. Paul Crawford Silver badge

      Re: Oh, goodie!

      Remember this: C is basically a universal assembler, created to allow an OS to be written in a largely machine-independent manner. As a result it allows all sorts of potentially dangerous actions (in particular pointers, but not helped by some of the more odd/obscure syntax that sticks around).

      Rule #1) If you can't program in assembler with any degree of success then don't use C

      Rule #2) C++ adds some better features, and adds some worse features

      Rule #3) If safety is more important than performance or universal support use another language.

      Rule #3.9999999) Don't use flaky Pentium FPUs

      1. Anonymous Coward
        Anonymous Coward

        "If safety is more important than performance or universal support use another language."

        That's why an OS shouldn't be written in C/C++ any longer... <G>

        1. Paul Crawford Silver badge

          Re: That's why an OS shouldn't be written in C/C++

          Oh yes, most of the OS kernel should as it needs that sort of memory wrangling and I/O poking sort of thing.

          Most of the user-land tools and utilises probably not...

      2. Salamamba

        Re: Oh, goodie!

        upvoted as I remember the FPU issues coincided with my conversion to AMD processors

      3. Anonymous Coward
        Anonymous Coward

        Re: Oh, goodie!

        >Remember this: C is basically a universal assembler <

        Remember this: FORTRAN is basically a universal assembler

        Remember this: COBOL is basically a universal assembler

        Or, for those of you too young to remember: read up on a little history.

        1. Paul Crawford Silver badge

          Re: Oh, goodie!

          "FORTRAN is basically a universal assembler"

          Not really. While *ALL* compiled languages eventually result in assembly-level instructions, C is a slightly special case in that it allows quite easy means of arbitrarily addressing memory locations and interacting with asynchronous events such as signals/interrupts. It also has many bit-wise sort of options in terms of manipulating integers, bit fields in structures, etc, that are useful for hardware driver I/O, etc.

          That is not part of the usual FORTRAN syntax nor (I presume, not used) COBOL. E.g FORTAN 77 had no memory allocation support, you had to define fixed-size arrays at the start.

  5. karlkarl Silver badge

    Pretty much everything here can be avoided by using smart pointers. Unfortunately so many C++ libraries do not use these so the safety breaks at this point.

    And when using C libraries... well Rust will have the same issue, you need to make wrappers, and if these have faults, you get dangling pointers and unhappiness like that :(

    1. Anonymous Coward
      Anonymous Coward

      Really? Smart pointers save the world?

      They are a useful tool, but they won't stop you falling into most the traps that the standard sets for the unwary (think undefined behaviour).

    2. Anonymous Coward
      Anonymous Coward

      _

      If you understand how pointers work, 'smart pointers' only obfuscate.

      Eschew obfuscation.

      1. Zippy's Sausage Factory
        Joke

        Re: _

        Eschew obfuscation

        Sounds like the name of a modern death metal track. Seriously, seems bands have a competition among themselves to see how many polysyllabic words they can use per album that haven't been cited since the 1600s.

        I blame Slayer*

        Joke alert because ... er... this isn't a very serious post?

        * last time I looked up abascinate, "Reign In Blood" is cited from 1986 as the first usage for about 300 years, the show offs...

      2. Anonymous Coward
        Anonymous Coward

        "Eschew obfuscation"

        In C++, if you're not using smart pointers, you're going to reinvent them yourself, believe me. For example the lack of a "finally" statement fro try blocks inevitably leads to issues when you have to ensure some resources are always released.

        The religious faith in RAII creates problem when you create objects which are referenced through pointers because you can't allocate everything on the stack for big, complex applications and stacks are often limited resources - so you need a pointer that can destroy the referenced object when going out of scope - et voilà, a smart pointer... which is smart because the language is not.

        Languages which are using ARC have implied smart pointers, and they share the same issues. you need to have more than one type to address different uses, and ensure you use the right one. Plus some bottlenecks for concurrent accesses when the pointer is shared.

        1. Dan 55 Silver badge

          Re: "Eschew obfuscation"

          The religious faith in RAII creates problem when you create objects which are referenced through pointers because you can't allocate everything on the stack for big, complex applications and stacks are often limited resources

          malloc and new use the heap...

          1. Anonymous Coward
            Anonymous Coward

            Re: "Eschew obfuscation"

            Yeah really. IIUC the point of RAII is having the compiler do the new and delete for you, but new and delete nonetheless, so it would sort of _act_like_ objects on the stack-- which are free once execution leaves that scope-- not because it could or would _use_ the stack.

            NB: it's really not my business, I've decided that knowing lots of C++ is a liability :D

            1. Anonymous Coward
              Anonymous Coward

              Re: "Eschew obfuscation"

              n/m I misunderstood OP a bit. Of course 'not the stack' and they weren't implying it either.

    3. Anonymous Coward
      Anonymous Coward

      Smart pointers themselves are an hack to try to fix deficiencies of the C++ design, which C++ "designers" prefer not to address for religious reasons. Moreover, like all pests, they tend to proliferate and there's the risk to choose the wrong one if you don't know very well how each of them behaves.

      But many of the issues in that document stems from bad decision made more than forty years ago in C, borrowed in C++, instead of being deprecated. That's because C programmers like a "loose" language - because it's easier to write it with simple text editors, and that doesn't play well with security. Security works better with more "strict" languages - it's no surprise they become fashionable again - but they also require more discipline - and better tools - to be used.

      1. Brangdon

        re: for religious reasons

        That is, for backwards compatibility and efficiency.

        1. Anonymous Coward
          Anonymous Coward

          "for backwards compatibility and efficiency."

          And security issues.

          Backwards compatibility is important - but not when it creates more issues than it resolves. Efficiency too, We have insecure OSes, for example, because someone decided flat, overlapping address spaces for code and data were more "efficient" . so efficient ROP works perfectly.

          When people become so afraid of changes they feel the need to keep alive on outdated and risky designs, the only outcome will be huge security breaches. If in 1970 that was not a big issue, today it is, and even C/C++ need to change accordingly. Hundreds of pages about how write proper code won't be enough.

          It's just like believing more trained users will cause less mortal incidents, so you don't need safer devices by design.

      2. Anonymous Coward
        Mushroom

        not-so-smart with pointers

        > Smart pointers themselves are an hack to try to fix deficiencies of the C++ design, which C++ "designers" prefer not to address for religious reasons.

        Actually, no. Smart pointers are for programmers who can't handle memory management correctly.

        1. Anonymous Coward
          Anonymous Coward

          Re: not-so-smart with pointers

          Smart pointers are about communicating something to the reader.

          std::unique_ptr<Foo> foo ; // I own this, I can move ownership but I cant (share/copy), lifetime is as mine.

          std::shared_ptr<Foo> foo; // I have an interest in this, it might outlive me, but my share keeps it alive.

          std::weak_ptr<Foo> foo; // I have an interest in this, but my interest doesn't keep it alive.

          Foo * foo; // a wild pointer, set to whatever what on the stack last.

        2. Ken Hagan Gold badge

          Re: not-so-smart with pointers

          "Actually, no. Smart pointers are for programmers who can't handle memory management correctly."

          Actually, no. Smart pointers are for programmers who completely understand resource management, completely understand that different approaches are correct in different situations, and don't see why actually implementing any of those approaches should be their job, or why any of those approaches needed to be implemented more than once.

          Garbage collected languages are for those who get some, but not all, of the above points.

          1. Anonymous Coward
            Anonymous Coward

            Re: not-so-smart with pointers

            smart pointers are for programmers that understand when to let the language do their work for them.

            1. DrXym

              Re: not-so-smart with pointers

              "smart pointers are for programmers that understand when to let the language do their work for them."

              Smart pointers aren't part of the language. Nor are strings or a bunch of other things that other languages take for granted.

              Instead they're implemented by templates. While that's better than nothing it's certainly not as good as proper intrinsic types that can be checked by the compiler, generate efficient code and meaningful errors during compilation.

              1. Ken Hagan Gold badge

                Re: not-so-smart with pointers

                "While that's better than nothing it's certainly not as good as proper intrinsic types that can be checked by the compiler, generate efficient code and meaningful errors during compilation."

                If your compiler cannot generate efficient code from source then you need a new compiler. If your language doesn't let you state the constraints that apply for given types, you need a new language. If you need more meaningful errors than "look at this line -> here" then you need a new programmer.

                The advantage of implementing this stuff *outside* the language is that any third party can add to the toolbox. You don't need to wait for your compiler vendor to implement the feature and if you are trying to write portable code then you don't need to wait for *every* compiler vendor to implement the feature.

          2. Anonymous Coward
            Mushroom

            Re: not-so-smart with pointers

            > [ ... ] resource management

            That buzzword was invented specifically for programmers who couldn't handle memory management correctly, and got very offended when this inability was pointed out to them at code review time.

            It's not memory, it's a resource. Your program does not leak memory like a sieve, it is not optimized for efficient resource management.

            Sounds savant and less incompetent.

            1. Ken Hagan Gold badge

              Re: not-so-smart with pointers

              "[resource management] was invented specifically for programmers who couldn't handle memory management correctly"

              Really, I thought it was because files aren't memory, database transactions aren't memory, network connections aren't memory, windows aren't memory, graphics contexts aren't memory, function hooks and callbacks aren't memory, ...

              You are talking utter crap. The word "resource" is used here because exactly the same code can be used to manage just about anything that needs to be properly disposed of at some later point in time and you know, at the time of "acquisition", when and how that disposal ought to be done. That description applies to a huge range of use-cases, only a tiny fraction of which are related to memory management.

              1. Anonymous Coward
                Mushroom

                Re: not-so-smart with pointers

                > Really, I thought it was because files aren't memory, database transactions aren't memory, network connections aren't memory, windows aren't memory, graphics contexts aren't memory, function hooks and callbacks aren't memory, ...

                Actually, everything you enumerate above is just that: memory.

                Which leads me to question whether or not you have a modest and cursory understanding of computers and operating systems.

                What exactly do you believe that an open and valid FILE* pointer - if you are using the Standard C Library - refers to? Or points to? Or a fully initialized and open std::iostream, if you are using the C++ Standard Library? Or what does an open and valid XDisplay* pointer point to, if you're programming in X?

                Speaking of the Standard C Library or Xlib: are there any smart pointers in the Standard C Library or in Xlib? Do you know the answer to this simple question?

                Nework connections aren't memory? Really? What are they, then?

                Functions aren't memory? Do you even understand what a function call is, and how it works?

                I'll educate you now: these are all pieces of memory, and they all point, or refer, to memory. So are database transactions. They are not to some magic meaningless bullshit called a resource, or whatever other meaningless buzzword the industry has managed to come up with.

                Next time around, read more and type less. Start with Wikipedia. You might learn something.

                1. Brangdon

                  Re: everything is memory

                  There is more to a data type than its memory. There will, for example, be class invariants that need to be preserved. If you see everything as a just bag of bytes then you are missing some powerful tools. For this reason, a file handle is more than a pointer to memory. It has meaning beyond bytes.

                  1. Anonymous Coward
                    Joke

                    Re: everything is memory

                    IINM most if not all of that meaning (metadata) is between you and the compiler, regarding how you expect it to see your beautiful grid of bytes before it throws them into the bag. :D Well, at least for "unsafe" languages like C/C++, until they CA-glue some introspection bits, anyway...

        3. John Smith 19 Gold badge
          Unhappy

          "Smart pointers are for programmers who can't handle memory management correctly."

          Whenever you hear "buffer overflow" that's another of those programmers who can't do this.

          Of which there seem to be a very large number.

          1. Anonymous Coward
            Angel

            Re: "Smart pointers are for programmers who can't handle memory management correctly."

            > Of which there seem to be a very large number.

            If you read Ken Hagan's seminal, ground-breaking explanation of what is and isn't memory in a computer operating system, on the previous page, it will become apparent why the number of programmers who don't know what they are doing is indeed very large. At any rate, larger than it should be.

    4. DrXym

      Smart pointers are much better than raw pointers but they're no panacea.

      Shared pointers can hopelessly muddle the lifetime of the object, and aren't suitable in places such as graphs / trees where parent / children can't hold mutual references to each other without surgery. They also don't protect you from race conditions in multi-threaded code. In C++, they don't work on new[]/delete[] either without specialised smart pointers for arrays. They also won't save your arse if you have a smart pointer pointing to a base class but neglected to make the destructor virtual.

      Their main benefit is they free the object when they go out of scope, or an exception is thrown, and can overload -> to throw an exception. This is all very beneficial and encouraged behaviour but it's not the only thing that needs to be used.

      As for Rust calling C... Every language with FFI bindings to C can screw up. Most C library apis will usually have an Init/Shutdown function plus Alloc/Free functions for creating objects. The best way to deal with a C library is a RAII wrapper of some kind. Rust also has a tool called bindgen (https://github.com/servo/rust-bindgen/blob/master/README.md) which can parse a C header file and produce a stub in Rust to call but it still requires layer on top to manage resources / memory.

  6. Robin

    Rules

    Well I've read through the rules, but Rule 34 seems to be missing?

    Also, the first Rule of C++ Club seems to be wrong.

    1. Zippy's Sausage Factory
      Joke

      Re: Rules

      Does the first rule of C++ club multiply inherit from the 2nd and the 4th rules of C++ club?

  7. LionelB Silver badge

    This is no mere listicle: it weighs in at 435 pages

    TL;DR

    1. horse of a different color

      Re: This is no mere listicle: it weighs in at 435 pages

      RTFM :)

  8. Red Ted
    Thumb Up

    To quote Bjarne Stroustrup

    C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off.

  9. Arthur the cat Silver badge
    Facepalm

    To download the document

    you need to pass a CAPTCHA. A security measure better defeated by AI than humans.

    Sigh.

  10. DCFusor
    Holmes

    Long experience

    Been in the software game quite some time (Fortran was the hot new replacement language for assembly and COBOL)...

    Long experience has shown that making it possible for monkeys to write code just gets you monkey code. Drag-drop anything, semi-automated error checking, frameworks that force you into models that may not be correct for the task some idiot tries to force fit and so forth.

    Java (among others) was going to fix that - no pointers to dangle, so everything is a reference? (if you know CS you'll know why this is funny) - and GC that can hang your process for some time whenever it feels like it, so forget any hard deadline...

    OLE, ActiveX, DCOM - code in your dsta. What a howler! What a great safety feature! /s

    The truth is, sad as it is for managers wanting low pay grunts to do important things is that there is no answer to the problem that actually works (see tech solutions to social issues). Even the monkey and Shakespeare model requires someone to notice when the monkey writes a sonnet.

    I still believe that it's better to know how to code, design with memory/object/pointer lifetime and scope in mind from the start, and if that's too hard for you - get out of the room or work on the design till you know and can code those types of issues FIRST. No new without the delete (and they better match in number) or whatever construct you use (we did a lot with the stack which eliminates a lot of that, and by gawd a simple text search will find strcpy so you can replace it with strncpy over a large code base proactively). Of course memory issues are just one of the areas one should be getting right in the design before the first line of code goes in.

    Horses for courses is part of the design process, one size never did fit all. Language fad du jour is not going to fix it for you. If it could you wouldn't need programmers at all - a definition put into the computer would result in perfect or at least good code...so really, that's the problem, making that definition correct and in enough detail.

    Coding at the terminal should be punishable. We banned it at my outfit right off since we had to support what we wrote...coding is the easy part and pretending you don't need a design doesn't make that true - and no one I've ever met designs better in front of a terminal than on paper/whiteboard/whatever with brainstorming and red-teaming. It's faster to get it right before building - just like we use architects and plans for construction of other important things.

    Rust might be nice, but like all others, it's fad of the day, not "the all singing all dancing answer to all problems". For one-off code, one might use a language that saves programmer time instead of computer time and safety, if the code is only going to be run in a safe sandbox couple of times to get an answer once...horses for courses.

    1. Anonymous Coward
      Anonymous Coward

      Re: Long experience

      But what happens when the real world intrudes, your superiors don't know code, and you have a fixed deadline that's too short?

      Coding secure sounds nice until you're forced to code in too short a deadline and under too small a budget. Oh, and the job market's pretty tight as well, so there's no next ship to which to jump.

  11. Quentin North
    FAIL

    Pascal is the future!

    Bring back Pascal with runtime checking. None of this directly accessing memory nonsense.

    1. Anonymous Coward
      Anonymous Coward

      Re: Pascal is the future!

      So what happens when maximum performance is demanded and you're coding for an underpowered SoC?

      1. david 12 Silver badge

        Re: Pascal is the future!

        >So what happens when maximum performance is demanded and you're coding for an underpowered SoC?<

        Well, actually high power compilers allow you to do runtime checks with minimal performance penalty, but as I understand it, that's still a research project.

        On the other hand, tightly specified compiler managed pointer variables ("byref") automatically give you more efficient code with fewer errors, so you'll be ahead there, and the Pascal/FORTRAN math and logic semantics give you two more big boosts.

    2. Mike 16

      Re: Pascal is the future!

      Oddly, the most "amusing" errors of the "buffer overflow" sort I encountered were in systems coded in PASCAL. Of course, the "overflows" were in parts of the system that were not main memory, but the disk. Yes, the OS code was written in PASCAL, and apparently the authors had so ingrained in them that "the language will keep me from doing anything stupid" that their filesystem code did not bother to check their own metadata, and so blithely wrote outside the "limits" of the filesystem that they were building. There is no Silver Bullet.

      I suspect this is related to the observation by insurance companies that drivers of cars with anti-skid braking systems tended to drive more aggressively, with sometimes fatal result.

      1. swm

        Re: Pascal is the future!

        "I suspect this is related to the observation by insurance companies that drivers of cars with anti-skid braking systems tended to drive more aggressively, with sometimes fatal result."

        The trouble with anti-skid brakes is that the stopping distance is much longer than without them. Don't take control from me when I know what I am doing. A 4-wheel skid might be appropriate in some circumstances. I have learned to brake just short of the point where the ABS starts operating and can stop much quicker. I would like to totally disable the system.

        1. Charles 9

          Re: Pascal is the future!

          "Don't take control from me when I know what I am doing."

          But then, the big question. Do you KNOW what you're doing, or do you THINK you know what you're doing?

          1. jake Silver badge

            Re: Pascal is the future!

            Well, I've been contributing to the Linux Kernel for over twenty years and I haven't (yet) been sworn at by Linus. I think I have a few clues.

  12. Kevin McMurtrie Silver badge

    Compiler help

    In most cases the compiler knows or could know when you're doing something wrong. If it doesn't know what you're doing, that's also a good sign that you're doing it wrong. I don't write C++ often, but an IDE that highlights potential problems decimates debugging time. C++ is complex as hell, and some of the helpful language tricks to reduce complexity actually make it more complex.

  13. Bronek Kozicki

    Right

    Sniggering remarks "do not use C++" or "another boring set of guidelines" aside, I'm wondering if there could be some constructive criticism found here ? Something like "they missed this potential issue" or "that one is C problem, not specific to C++ so it belongs elsewhere".

  14. Claptrap314 Silver badge
    Facepalm

    Umm...

    Haven't really had the pain of using C++ yet, so I took a look at C. I'm not particularly up on that either, but I found some hair-raising stuff in the integers section, to wit: "INT30-C-EX2: Checks for wraparound can be omitted when it can be determined at compile time that wraparound will not occur. As such, the following operations on unsigned integers require no validation:

    ...

    Subtracting any variable from its type's maximum; for example, any unsigned int may safely be subtracted from UINT_MAX.

    "

    Now admittedly, this is in the subsection on unsigned ints, but to leave something like this just hanging there is begging for someone to get it wrong.

    It gets better. (worse)

    "INT30-C-EX3. The left-shift operator takes two operands of integer type. Unsigned left shift << can exhibit modulo behavior (wrapping). This exception is provided because of common usage, because this behavior is usually expected by the programmer, and because the behavior is well defined. For examples of usage of the left-shift operator, see INT34-C. Do not shift an expression by a negative number of bits or by greater than or equal to the number of bits that exist in the operand."

    NO IT IS NOT! (Of course, they are contradicting themselves here.)

    I've not been confirming this recently, but 15 years ago, both X86 & PPC processors had a very odd behaviour regarding regarding overshifting. They were (are) intended to support MP computations, but unless you have been told, or have done the experiments, you do NOT know the actual behaviour of these operations. What I do know is that I blew the minds of some folks who had just taken a Scala class by demonstrating the behaviour.

    The integers are a strange and chaotic set. Integer registers are for the damned and the insane. That CERT would issue rules without making VERY clear just how dangerous the very things it is discussing are is...disturbing.

    1. swm

      Re: Umm...

      Any overflow on signed integers is undefined behavior - the Earth may fall into the sun. Unsigned integers are guaranteed to wrap. Shifting by more than the word length is also undefined behavior. Any undefined behavior is not portable and may behave differently at different optimization levels.

      A serious programmer reads the language standard.

  15. thomn8r

    I've not done C++ since the late 90's, so I did not recognize most of the constructs in the list. Now I just feel old.

  16. Herby

    Maybe the first rule should be...

    (I'm being VERY cynical here)

    Don't use C++

    If you start with that premise, and note exceptions, you might have something, you never know. Of course this leads to LOTS of "this" is better than "that" style arguments. These quickly degrade into religious wars sooner or later.

    My take: The language book written by the authors of C is about 1/2 inch thick. The language book written by the author of C++ is around 1.5 inches thick. To me this implies that the fancy language is THREE (maybe more) times more complex. I can just barely remember the minute details of C so I barely need to look up things. Memorizing 3 times as much is a big burden for me (look, I'm getting old!), so the language is MUCH more difficult. So I follow rule zero as stated above, and let it go.

    Generally languages have gotten more complex as time goes by, and have become more difficult to understand as a whole. Sometimes I long for the days of Fortran II (yes, I used it at one time!).

  17. EarthDog

    "Don't be stupid" advice #1

    Don't use C++

    1. david 12 Silver badge

      Re: "Don't be stupid" advice #1

      Firstly, there are differences between the C and C++ specification that allow almost-ordinary C++ code to be more efficient than C (although admittedly, if you wanted efficient code, you wouldn't start there).

      Secondly, once you ignore OO, C++ provides better encapsulation and abstraction than C (although admittedly, if you wanted encapsulation and abstraction, you wouldn't start there)

      Thirdly, C++ gives you the STL, which allows you to avoid boatloads of your own error-prone code.

      Horses for courses. Just because CS graduates code in C++, doesn't mean that everyone using C++ has no excuse.

POST COMMENT House rules

Not a member of The Register? Create a new account here.

  • Enter your comment

  • Add an icon

Anonymous cowards cannot choose their icon