
JPL Institutional Coding Standard for the C Programming Language (2009) [pdf] - Alupis
https://lars-lab.jpl.nasa.gov/JPL_Coding_Standard_C.pdf
======
AnimalMuppet
Run through a state-of-the-art static analysis tool _with no warnings_? That's
seriously stringent.

And then, rule 23: "All #else, #elif and #endif preprocessor directives shall
reside in the same file as the #if or #ifdef directive to which they are
related." It never even _occurred_ to me that anyone might do otherwise, but
yeah, that's a _real_ good thing to forbid. (I once failed to close a C-style
comment at the end of an include file. It was the last include file, so the
next couple of lines in the C file were commented out - which happened to be
the main() function name and the opening curly brace. It then treated the rest
of main() as file-level variable declarations, which was fine until we got to
the actual code. I got 1800 compiler errors from that...)

~~~
as-j
You know rule 23 exists for a reason, someone thought it would be a good
idea.....egads, I wonder what evil horrible thing they did.

------
ZachWick
In previous embedded work, I've had to follow the MISRA C [0] guidelines,
which I suspect are roughly similar to the JPL guidelines (but I can't get to
the PDF at the moment due to the bad SSL cert).

[0]
[https://en.wikipedia.org/wiki/MISRA_C](https://en.wikipedia.org/wiki/MISRA_C)

~~~
guitarbill
> Two earlier efforts have most influenced the contents of this standard. The
> first is the MISRA-C coding guideline from 2004 [...]

Not just similar, but based on MISRA C!

MISRA C can be a total PITA though (I get why, but it doesn't make it any less
annoying). Some well known storage products follow similar principles without
being quite so stringent. It's quite a nice middle ground, and - if you are,
err, detail oriented - can be a less aggravating experience than sloppy,
higher level codebases (yes, Java, I'm looking at you mainly).

~~~
carlmr
MISRA C is annoying mostly if you have to change the codebase to fit the
standard. If you iteratively solve MISRA warnings they become second nature
and you almost don't make them anymore.

What is annoying is the paperwork when you need a deviation. However that's
kind of the point of the process. Make it annoying enough that people really
think about whether the deviation is necessary.

At the same time it's only a coding standard. Not a panacea for all your
coding issues. You can have 100% MISRA conformant spaghetti.

It does reduce the "shoot yourself in the foot" surface area a little bit
though.

~~~
acprog42
> You can have 100% MISRA conformant spaghetti.

IMHO some of MISRA rules lead directly to hard to read/maintain code. Consider
a function that:

1\. opens a file 2\. allocates enough memory to store the whole file 3\. reads
the file 4\. return the allocated buffer on success or NULL on failure

You want to write it so it doesn't leak either memory or file handles whether
successful or not (if successful ownership of the memory buffer is passed to
the caller so it must not be freed in that case).

To be MISRA compliant you'd either end up with a "Christmas tree" of nested
scopes or if-statements with extra && in them (pseudo C-code):

    
    
        char *buf = NULL;
        FILE *fh = fopen(...);
        if (fh) {
          if (success(fseek(fh, end))) {
            long int sz = ftell(fh);
            if (sz > 0) {
              buf = malloc(sz);
              if (buf) {
                if (failed(fread(fh, buf))) {
                  report_error();
                  free(buf);
                  buf = NULL;
                }
              } else {
                report_error();
              }
            } else {
              report_error();
            }
          } else {
            report_error();
          }
          fclose(fh);
        } else {
          report_error();
        }
        return buf;
    

However if you were allowed to use goto with a single exit-label the code
would be much cleaner and easier to follow:

    
    
        char *buf = NULL;
        char *rv = NULL;
        FILE *fh = fopen(...);
        if (!fh) {
          report_error();
          goto exit;
        }
        if (fail(fseek(fh, end))) {
          report_error();
          goto exit;
        }
        long int sz = ftell(fh);
        if (sz <= 0) {
          report_error();
          goto exit;
        }
        buf = malloc(sz);
        if (!buf) {
          report_error();
          goto exit;
        }
        if (failed(fread(fh, buf))) {
          report_error();
          goto exit;
        }
        rv = buf;
        buf = NULL;

exit: if (fh) { fclose(fh); } if (buf) { free(buf); } return rv;

~~~
kelvich
Actually you can do that without goto's, by using do {} while loop and break:

    
    
        FILE *fh;
        char *buf = NULL;
        char *rv = NULL;
    
        do {
            fh = fopen(...);
            if (!fh) {
                report_error();
                break;
            }
    
            if (fail(fseek(fh, end))) {
                report_error();
                break;
            }
    
            long int sz = ftell(fh);
            if (sz <= 0) {
                report_error();
                break;
            }
    
            buf = malloc(sz);
            if (!buf) {
                report_error();
                break;
            }
            if (failed(fread(fh, buf))) {
                report_error();
                break;
            }
    
            rv = buf;
            buf = NULL;
        } while(false);
    
        if (fh)
            fclose(fh);
        
        if (buf)
            free(buf);
        
        return rv;

~~~
acprog42
Sure, that would pass the `grep -r goto __` test, but is just a more
convoluted way of doing the same thing.

~~~
coldtea
That's fine: the intention was not to do something else, but to avoid goto
while still doing the same functionality.

Plus, it might be slightly more convoluted than goto, but is less convoluted
than the original over-nested code, which was the intention.

~~~
acprog42
Which brings us back full circle to the point I was originally trying to
convey: _if_ a coding standard forces you to write more convoluted and harder-
to-read code just to _work around_ some of its rules, that is a clear failure
of said standard.

Fortunately MISRA seems to have gotten back some sanity in the 2012 revision
compared to the one the above JPL standard is based on.

~~~
coldtea
> _Which brings us back full circle to the point I was originally trying to
> convey: if a coding standard forces you to write more convoluted and harder-
> to-read code just to work around some of its rules, that is a clear failure
> of said standard._

Only if the "more convoluted and harder-to-read code" is worse than what the
standard tries to avoid.

A standard that calls for not allocating memory dynamically for example might
result in less elegant code than one that does, for example, but that's not a
"clear failure" since that away it avoids the uncertainty and variable runtime
performance that malloc brings.

I'm addressing the general claim here, that "if a coding standard forces you
to write more convoluted and harder-to-read code just to work around some of
its rules, that is a clear failure of said standard" \-- not specifically
where the particular no-goto rule was justified.

A standard can be perfectly valid and good in restricting things even if that
forces programmers to write "less elegant code" \-- as long as this is
necessary to fulfil some other objective of the standard (e.g. easy formal
verification or real-time behavior).

------
cpeterso
A CppCon 2014 presentation about safety-critical C/C++ coding standards for a
different "J" acronym: the Joint Strike Fighter (JSF).

"Using C++ on Mission and Safety Critical Platforms".

[https://www.youtube.com/watch?v=sRe77Mdna0Y](https://www.youtube.com/watch?v=sRe77Mdna0Y)

~~~
metaphor
Thanks for sharing. Although it isn't my application domain, their
considerations were nevertheless interesting.

On a general note, this bullet under "Lessons Learned" circa 48:00 hits home:

> _A rationale for each rule educates developers and gets their buy-in_

It's been my experience that standards which embody this philosophy are the
most pleasurable to work with. On the flip side, I've dealt with "updated"
standards which have directly perpetuated technical debt as a consequence of
rules defined to address temporal issues that were relevant at the time but
passed over in subsequent revisions due to lost tribal knowledge...it's always
a challenge addressing this class of rule, even if just trying explain to a
new developer on the team without making that person feel like a complete
tool.

------
uasm
> "Do not use goto, setjmp or longjmp."

Error handling in C without those primitives will almost always result in
horrible code. They should've made an exception here: "goto error;" should've
been allowed and encouraged.

~~~
coldtea
> _Error handling in C without those primitives will almost always result in
> horrible code_

They don't care for nice code. They care for easily statically checked and
verified code.

~~~
philpem
As I said else-thread, there's actually a variation in MISRA-C-2012 (or
possibly one of the addenda) for this.

Error handling using 'goto' is allowed, as long as you're jumping forward
(i.e. to or near the end of the function). You can't go backwards through the
code.

It may require a variation in the project's coding spec but it's certainly
possible (because I've been there and done it!)

------
laveur
Apparently the SSL cert for this got revoked... I wonder if anyone at nasa
knows...

~~~
Alupis
Looks valid on my machine (win10, chrome)

~~~
cbsks
Safari on iOS does not trust the certificate

~~~
brandonjm
Safari, Chrome and Firefox all do not trust it on macOS as well.

~~~
saagarjha
My Safari does, to give another viewpoint.

------
saagarjha
> All C code shall conform to the ISO/IEC 9899-1999(E) standard for the C
> programming language, with no reliance on undefined or unspecified behavior.

Easier said than done ;)

~~~
pjmlp
In those environments use of static analysers is enforced, which kind of
helps.

------
CDSlice
I don't know very much about C, but it looks to me that no_std Rust with a
custom allocator could let you fulfill most of these requirements and keep
most of Rust's nice features like Result for error handling. I wonder if
JPL/NASA will consider using Rust for any of their future missions.

~~~
0815test
> I wonder if JPL/NASA will consider using Rust for any of their future
> missions.

You are quite welcome to try, but don't expect any help - the Rust Evangelism
Strike Force is way too busy focusing on world domination _on Earth_ for Rust,
at the moment. Missions in outer space are still outside their remit.

~~~
steveklabnik
We had a talk at RustConf this year about Rust in space...

~~~
CDSlice
Was it recorded? That sounds pretty interesting and I would like to watch it.

~~~
steveklabnik
[https://m.youtube.com/watch?v=Vq03Ba7W95I](https://m.youtube.com/watch?v=Vq03Ba7W95I)

------
okl
Coding standards can be a pain, but most rules make sense and if they don't
make your code difficult to read and unwieldy you should probably create an
exception.

One example where such an exception would have been justified is found in cFE:
[https://github.com/nasa/cFE/blob/04c0cc342415575f855dc00960a...](https://github.com/nasa/cFE/blob/04c0cc342415575f855dc00960afc8daedd8a46e/cfe/fsw/cfe-
core/unit-test/evs_UT.c#L106)

Thousands of lines of clutter in the unit tests because they are not using a
function-like macro.

------
dima55
Not an "institutional coding standard" by any means. Maybe some groups conform
to this, but I haven't come across any.

~~~
jvanderbot
Not all code complies. But not all code flies.

My experience has been that as a mission system passes gates in the years
before launch, they asymptotically approach these standards, with exceptions
approved by named individuals and reviewed. I doubt many institutional
products or teams conform strictly on all projects. That'd be quite
unproductive.

~~~
dima55
Not all code is flight code :)

------
kensai
Found a working PDF link also here: [http://everyspec.com/NASA/NASA-
JPL/JPL-D-60411_VER-1_32832/](http://everyspec.com/NASA/NASA-
JPL/JPL-D-60411_VER-1_32832/)

------
arthurcolle
Content unavailable. Anyone have a decent mirror?

~~~
guitarbill
Just `curl` it, or use something that allows you to ignore certs.

~~~
arthurcolle
Thanks guitarbill

------
enriquto
This is a beautiful document and a very sound set of rules.

------
GnarfGnarf
All in all, sound advice.

No recursion? That's a deal breaker.

~~~
lasagnaphil
No recursion kinda makes sense, because you really don't want to have an
accidental stack overflow while the airplane is off the ground...

Interestingly, one of the goals of the Zig language (marketed as a replacement
for C, currently in development), is to eliminate stack overflow while keeping
recursion (by enabling the user to allocate stack frames in the heap).

[https://github.com/ziglang/zig/issues/1639](https://github.com/ziglang/zig/issues/1639)

~~~
biesnecker
Wouldn't that eventually just lead to an OOM? Most of the time the recursion I
write is either well-formed and lives nicely in the stack or poorly-formed and
would consume all the memory in the universe if given the opportunity.

------
AnimalMuppet
(2009)

~~~
Alupis
There does not appear to be a newer version. Not sure if adding the date here
is all that relevant... Not like C programming changes that much these days.

~~~
jvanderbot
Mars rovers don't iterate quickly. This was very much my experience when
working on those teams.

------
xvilka
Best advice - not to use C wherever possible. There are better languages for
many areas. Speaking from my decade of experience as C programmer.

~~~
jakeinspace
Pretty much unavoidable when it comes to real time embedded systems. Your
options in that world are pretty limited, especially on space-rated processors
which are generally many generations old, and can't necessarily handle huge
performance overheads.

~~~
froh
I seriously wonder why Ada didn't catch on more?

~~~
burfog
The compilers were expensive.

This is probably because Ada was mandated for government projects. The people
buying compilers were most likely able to charge that expense to the
government, possibly even with a mark-up.

The language had a weird temporary resurgence a few years back. It seems to
have started by the free Ada compilers becoming decent and by people starting
to get serious about security holes. It seems to have ended due to rust
claiming that niche.

~~~
pjmlp
If you are talking about HN bubble effect yes.

In production code powering high integrity systems, certified compilers and
industry safety norms, Rust still has a lot to catchup over Ada.

