News for hackers. Stuff that matters.

acprog42

Re:A Working Mathematician’s Guide to Parsing on Friday May 03, 2019 @09:42AM (#19818333)
But killing an ant with a nuclear bomb is moar funnier! Don't stop the fun!
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.

Yeah, seems like it actually allows my second example which is good! :)
Sure, that would pass the `grep -r goto ` test, but is just a more convoluted way of doing the same thing.
> Most Misra software is embedded without dynamic allocation though

True, but I've seen enough MISRA code bases plagued with the "Christmas tree" layout even if dynamic memory allocation isn't allowed. This was just a generic example most people can relate to.

True, it would be kind of analogue to try/except/finally if you do that.
Too little karma to edit and fix indentation. Anyway given the above functions, think about adding support for only returning the buffer if the file contains a specific word. While certainly doable in both cases I would at least feel more uncertain editing the first without accidentally creating a bug...
> 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;