This should never happen
github.com
github.com
I was caught a bit off guard, but I assumed the customer must know someone at the company, since Brian was the name of the previous electrical engineer/firmware programmer. So, I told them that Brian didn't work here any more, but was there anything that I could help them with? The customer said, "Well, the device says that I should call Brian". I was confused by this, and asked a lot of questions until I determined that the device was actually displaying "CALL BRIAN" on the LCD display.
This was quite unusual, and at first I didn't believe the customer, until he sent a picture of the device showing the message.
So, I dug into the code, and quickly found the "Call Brian" error condition. It was definitely one of those "this should never happen" cases. I presume that Brian had put that in during firmware development to catch an error case he was afraid might happen due to overwriting valid memory locations.
I got the device back, and found out that the device had a processor problem (I don't remember exactly what) that would write corrupted data to memory. So, really, it should never happen.
That particular device has now been in production for 10 years, and that is the only time that error has ever appeared.
I was compiling some tiny test program on it, and it spit out an error message that said something to the extent of "This shouldn't happen. Email Dave and tell him what you did - david<something>@digital.com." I ended up forwarding it to our IT department whom I assume sent it on to DEC. I don't know if Dave ever saw it or not, though.
struct somestruct {
int s1;
int data;
char * moreData;
int s2;
}
When the caller of the API needed to call my code, it had to first call a function to get an instance of the struct. This constructor like code would allocate the memory for the struct, and then set s1 and s2 to 0xDEADBEEF;The user would then fill out the rest of the struct and pass it back in as an argument to another call.
If either s1 or s2 wasn't 0xDEADBEEF, I would throw an error to the caller.
I helped me catch a lot of cases where the caller to the API had overrun some string while filling out the inputs.
He had a structure that was getting overwritten with garbage due to an overrun somewhere else in the code. Rather than debugging and trying to find out what was doing it he just put "char temp[1000];" at the top of the struct to "absorb the damage".
I believe it's still running like that in production to this day.
That's funny.
The code above got written that way because at my first job, I inherited a godawful business charting API written by the lead developer.
The input to the API was a struct with 70-80 members that the caller had to fill in and there were no defaults for anything! Naturally there were not just scalars, but lots of arrays and strings in the struct, which could easily be overrun or often left null.
The users, quite understandably, didn't fill out everything, which led to frequent crashes in _my_ code because that's where the pointers would get dereferenced.
When they would see that the crash was not in their code, the users of the API would punt the error to me even though it was their bad input that caused the problem. This would happen 10-12 times a day.
I rewrote the entire thing in a paranoid style , employing the trick above and others to try and ensure that if there was bad input, that it would always crash on their side of the fence.
After I was done I got one legitimate bug report for the code, even though it was in use worldwide in our medium sized company.
However this might not have caught the error condition described upthread. That condition might have overwritten data or moreData without touching s1 or s2.
Otherwise, great!
Also to all those ready to do a checksum on a struct, rememember that structs are plattform dependant (padding bytes).
1. Store embedded system state in data structure.
2. Calculate a checksum for that data structure.
3. Verify that checksum is correct.
HW Solution:
Lockstep Execution/ECC memory, etc.
If too many errors happens, the checksum can be correct even though the content is corrupted.
Hum... I know what you think: ThisShouldNeverHappen
When exploited by human it is called a collision attack. Works pretty well, so many people trust but never check.
The usual use is to catch errors caused by misuse of a method. There is some invariant that the method assumes but is not enforced by the type signature of the interface. So if something goes wrong in outside code, or someone tries to use the method incorrectly, the invariant is not satisfied. When you catch such a problem, the current code context is FUBAR. The question is how aggressively to bail out : spew errors to a log and proceed with some GIGO calculation? Throw an exception? Exit the program?
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException
Since it can throw a checked exception you have to catch it, which generally is fine, but consider this case: someString.getBytes("UTF-8");
This call can never fail (support for UTF-8 encoding is required in Java) but in my case I have to do something with the exception in the catch statement or our static code analysis tool will start complaining (and rightfully so). So that's where I'll log a 'can't happen error'. It truly cannot happen. enum Whatever { FOO, BAR }
if (whatever == FOO) {
} else if (whatever == BAR) {
} else {
// Should never happen!
}
[0] http://stackoverflow.com/questions/5013194/why-is-default-re... throw new AssertionError("Should never happen"); someString.getBytes(StandardCharsets.UTF_8);
(Charset.forName doesn't throw either, StandardCharsets avoid stringly-typed code but it's not available on 1.6 so if you're still stuck there Charset.forName works)An ExceptT or Maybe monad for handling encoding errors feels a lot like throwing exceptions, although they are less disruptive than exceptions. I'd probably represent a decoder as a function with type ByteString -> ErrorT ParseError m Text, which is neither an ADT or Typeclass. It's a 3rd solution. Either that or an Attoparsec parser, which is probably equivalent. An encoder seems like it shouldn't fail at all, but if it eventually forks out to one of the C locale functions I can see it throwing errors too.
Meanwhile, in the real world, Data.Text.Encoding uses a 4th solution implementing decodeUtf8With and encodeUtf8 that ultimately represents the UTF-8 encoding as a pair of FFI functions with these signatures:
foreign import ccall unsafe "_hs_text_decode_utf8" c_decode_utf8
:: MutableByteArray# s -> Ptr CSize
-> Ptr Word8 -> Ptr Word8 -> IO (Ptr Word8)
and this one: foreign import ccall unsafe "_hs_text_encode_utf8" c_encode_utf8
:: Ptr (Ptr Word8) -> ByteArray# -> CSize -> CSize -> IO ()
text-icu also ultimately represents an encoding as an opaque pointer returned by the ICU library, and works in the IO monad. So it too could fail in similar ways. Errors throw an exception of type ICUError, which the caller can catch using the 'catch' function from Control.Exception.The encoding library does use typeclasses like you suggest, but I'm not sure anybody uses it. Sometimes people drop in #haskell and complain about that library, and the response is usually "don't use that; use the one in Data.Text.Encoding instead".
I don't use Rust, but if the language is at all practical, I imagine they shuttle their equivalent of pointers and bytestrings around and depend on foreign C libraries and locales just the same. Probably they don't want to change the core library every time the Unicode Consortium publishes a new encoding scheme, so I can't imagine them exposing only a closed type.
So, looking purely at the signature and comparing it to examples from a language you suggested, it doesn't appear to be poorly designed at all. It's exactly what I would expect and want in any language, and the library consensus seems to agree. I think you're just imagining the grass being greener on the other side.
xs = if p x then concat [[x, "bar"], foos] else "baz" : foos
ys = tail xs
Then you know that the call to tail is not going to fail in your code, because the input has a guaranteed minimum length of either 1 or 2. You can't make that same guarantee about tail in isolation, though.BTW I made a (almost religious) habit out of ensuring that everything I touch is encoded UTF-8 or can be converted to that as I have been bitten several times hard by unexpected encoding stuff. Therefore, the above problem catches me pretty often.
It happens a lot to me in Rust and Go.
GCC also has an extension for that: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index... which Clang supports: http://clang.llvm.org/docs/LanguageExtensions.html#builtin-u...
https://raw.githubusercontent.com/bjacob/builtin-unreachable...
Disagree on this. It has nothing to do with efficiency in context of unlikely events. As others have noted here, it is effectively an assertion of expected language/system/operating-environment properties. Think axioms.
You could be inclined to see it as "is not inclined to prove it", but I prefer to think it happens mostly because someone didn't think they changed something that could affect that (i.e. "I was sure that simple change to the boolean expression was equivalent when I made it...")
This is known as a reachability problem that in the general case cannot be proven. So, "not inclined" may actually mean "can't (in any reasonable amount of time)".
https://en.wikipedia.org/wiki/Rice%27s_theorem#Proof_by_redu...
Sometimes the important artifact is the executable in the larger context of the deployed system, rather than the code you generate it from.
You say it "is" leaky in the presence of memory corruption. However that is not necessarily true. One could model software memory verification within a type system. Meaning, you could guarantee at compile time that each time a variable is read it is verified via checksum against its last written value. This would not be particularly efficient, but the point stands that type systems can be used (and should be used) to model hardware failures.
This is no different than network link failures, etc...
The real world is messy. We can mitigate that, but we can never have mathematical purity.
But can I also just add that the error message remains unhelpful and outright "bad." You should absolutely have checks for "impossible" situations, but when those checks fail you need some way of determining which check failed (and cannot always assume you'll have stack backtrace, in particular if an end-user is telling you the error message).
For example you could do this: "Impossible Error in GetName(): {Exception}"
http://www.slideshare.net/bsotomay/uchicago-cmsc-23300-the-b...
Spouses less likely to run away into the dark abyss.
Bald inmate digging grows hair.
Player can die from lava while praying successfully.
Colonists will no longer stare each other to death.
Trash monsters will now have a chance to drop the intended cat ear colors.
Suicide animation speeds up search for apples, berries.
Fix trees not going to their burnt state when they go to sleep while on fire.
Potions are tasting much better now, especially the harmful ones.
https://twitter.com/TheStrangeLog/https://core.trac.wordpress.org/changeset/26851
---
The Pinking Shears stir from their slumber, awakened by what may seem, to those innocent in the ways of The Shears, a triviality, a nothing-of-consequence. But there are consequences indeed for recklessly trailing your whitespace. Naturally, they a dire!
One, two! One, two! And through and through
The Pinking Shears went snicker-snack!
They plucked your tail and with your space
They went sniksnuking back.
Let me tell you, that can be uncomfortable, so always pre-sniksnuk your trailing whites. May The Shears be with you.
They removed a trailing space from a comment! They have plenty of free time to write witty check-in comments.
I'm not sure if that's a 'bad' practice or just not the purest. But I don't think removing trailing comment space is bad in itself. As above, it probably didn't take any time at all; done automatically by a well-configured editor.
A common objection from new developers is that "commit messages are hard and they slow me down", so if that's how you feel (for example, you're starting a fresh project): go crazy with your commits and don't let them slow you down. But then rebase, squash, and edit the commits before sharing them.
If a developer consistently pushes commits like this, they should be guided by their team lead to understand their importance. But if over time they refused to improve them, in many cases that would eventually be fireable. Commits are the technical paper trail: whether used when diagnosing issues, merging, compiling release notes, or whatever. Making the messages clear is extremely important.
> But then rebase, squash, and edit the commits before
> sharing them.
And then realise that doing it properly in the first place most definitely would not have been a slow-down!But if I made a few commits, then pulled in someone's changes, then made a few more... well... http://xkcd.com/1597/
On the other hand, a lot of this was on a large PHP codebase, so the result soon became the stuff of legend :)
http://i3.kym-cdn.com/photos/images/newsfeed/000/731/143/3e3...
> fbd2658 Conflict all the fixes
Sounds like some amount of made-up work!
I mean it sounds awesome, but really hard.
In the masters program you can somewhat build your own degree after taking their core classes, so you can at least study what you're really interested in (or avoid the hard stuff like a lot of people did). Most of the profs had real industry experience too. A C++ class for example was taught by a guy who sold his company, now is a research fellow at a huge lab, and sits on the standards board. We got to bounce questions off Bjarne Stroustrup. Was pretty cool.
https://github.com/odbol/Reddit-Scheduler/commits/master
People definitely gave me flac for that.
[1] https://github.com/TheProjecter/propidle/blob/f0d5320e2a3d46...
https://msdn.microsoft.com/en-us/library/system.invalidopera...
My code made the Android OS throw this once. Not a terribly useful error to resolve.
Edit: My mistake. I misremembered. It's a logging function. I should have actually read the link I provided.
Which is anyways quite a lot of results, but then this search finds ThisShouldNeverHappenException, the string "this should never happen" and stuff like
// *This* gets run before every test.
if (b > d) {
fail("XX *should never happen*");
}
With quotations it's only about 500,000.Line 95 of this method [1] from this implementation [2] shows a max(mask(x), mask(y)), which is not associative but is a close proxy to max()(which is associative).
[1] https://github.com/addthis/stream-lib/blob/af045cb4199959c07...
[2] https://github.com/addthis/stream-lib/blob/master/src/main/j...
For example, based on external information you might know[1] that a condition inside of a loop will always be hit exactly one time. Your compiler or tools might not be able to determine that same thing. It may try to force you to do something like assign a value or whatever you did in that condition, that it can't guarantee has happened. In such a scenario, it might[2] make sense to have something like "this should never happen" after the loop, with a brief comment explaining why you've done this.
[1] I think this is the crux of the issue. We programmers often think we "know" something, but it might be an incorrect assumption. IMO part of being a good programmer is examining your assumptions at every step. The chasm is vast, between "the framework strongly guarantees X" and "the function that gets called before this one has done X already". The former is OK if you want to get work done, while the latter is much more brittle and possibly dangerous, depending on the level of coupling you're willing to accept.
[2] Nine times out of ten, a reorganization of the logic makes more sense. However, I do think there are scenarios where this pattern is the best choice given the options.
Also funny to see Java being the most verbose as usual, with its ThisShouldNeverHappenException.java
So that would've worked, too:
throw new RuntimeException("This should never happen!");
There would've been a difference between a Exception and a RuntimeException.Also sometimes this kind of RuntimeException happens when you convert one type into another and want to explictly call all cases something like that:
interface A
class AA implements A
class AB implements A
if (x instanceof AA) {}
else if (x instanceof AB) {}
else { throw new IllegalStateException; }
It's sometimes better to explicitly call all states instead of using the last else for the AB branch, since sometimes this will be extended later or the compiler would've throw an error since you have a return inside the if or else if.
Btw. Kotlin and Scala won't have this problem due to pattern matching.Those branches ought to disappear once the code and tests improve but we all know how that goes :-)
Usually because some insane abstraction was built over a concept and some of the implementations could throw something like IOException and some could not but of course the API throws IOException as a checked exception.
To me it seems like the search is grouping similar results in some way.
It is because C has no exception handling, and C coders still want to be sure.
For example once I had a game where I ended putting a couple "should never happen" in my code related to some OS stuff, and... the "should never happen" happened once, after figuring how to reproduce it, it was a driver bug (or something like that, happened years ago, I don't remember the details anymore, only remember that it went away after I switched from Alsa to OSS4 on my Linux box).
EDIT: should never happen is good against compiler bugs too, I've seen my fair share of them.
This one is more worrying I suppose: https://github.com/search?utf8=&q=FIXME&type=Code&ref=search...
E.g. "Should not happen — probably a bug in Apache Commons Math?"
Or "Shouldn't really happen, barring compiler bugs or cosmic rays"
As they told us, there is no such thing as probability of zero.
Snips from discussion in [1]: "We can expect problems, therefore, and should prepare for them. ... Garbage is bad enough, but garbage which is expected to contain a count to tell you how long it is can be much worse. ... The first time we ran this code it said 'can't happen' We got that message perhaps a hundred times in the process of adding the rest of the code... This experience speaks for itself; if you're going to walk a high-wire, use a net."
'Can't happen' is as much a pattern as 'Hello, World'... and it has the same genesis.
[1] Brian Kernighan, P.J. Plauger, 'Software Tools', Addison-Wesley 1976
https://github.com/search?q=ugly+hack&ref=cmdform&type=Code
https://github.com/search?utf8=%E2%9C%93&q=filename%3Aid_rsa...
https://github.com/search?p=3&q=extension%3Aphp+mysql_query+...
C++ 2.4M C 400K Java 150K ...
Sounds about right.
My initial reaction was "oh no" but as I thought about it, this explicitly indicates that the programmer actually thought about a case.
And is it any different than what most of us do in our unit tests? If we're expecting an exception that isn't thrown or the wrong exception is thrown, we force a test failure.
One of the goals our team is working towards is more robust and complete metric and log collection. We specifically want to capture exceptions that make it to the application server for analysis, but this assumes that the developer has a) considered all cases and b) caught intermediate exceptions and continued processing (or abort).
EDIT: Ha, turns out the link is just an attempt to prove that bugs that should never happen occur ten times more in C... Which is questionable.
void(int a, int b)
{
const int i = 0;
int result = a + b;
if (i > 0)
{
// This will never happen ;)
result = result / 0;
}
} You are not here.
Another message was in the Mac installer when there wasn't room to install: Your hard disk is too small.
That's the complete text of both messages, and yes, it displayed them to the customer. <sigh>After seeing these, I started going through the code and found a bunch of other rude, confusing, or jargony messages. It actually turned into a fun little project cleaning these up!
Anyway, if you read commits in Linux you'd find a lot of fuck in there. Quite amusing.
When I was an intern, I loved looking at MXR to find words like fuck: http://mxr.mozilla.org/mozilla-central/search?string=fuck
1: https://github.com/search?utf8=%E2%9C%93&q=should+not+get+he...
IF(.NOT.CHECK()) STOP 'xxx'
Anyway, somebody (not me) got into trouble when Very Serious Customers were offended by seeing the occasional STOP DAMN message at link time.
https://github.com/search?utf8=%E2%9C%93&q=should+not+get+he...
http://developer.android.com/reference/android/util/Log.html...
https://github.com/search?utf8=%E2%9C%93&q=%22no+idea+why+th...
https://github.com/search?utf8=%E2%9C%93&q=%22How+did+this+e...
[NB There is a related phenomena to do with a demo of a system that includes "adult content" (i.e. porn) - the likelihood of a user randomly stumbling upon this content is practically 100%, even if this content is a tiny part of the overall demo].
and so on. Still it would be a change from writing bad code.
I was working on site over the winter season when the hotel was closed down, a lovely old hotel high up in the Rockies. Every day I sat down and wanted to write some brilliant code but all I ever ended up writing was the same comment
All objects and no functions makes Jack a dull boy. over and over again.
Drove me quite mad actually.
Sometimes I feel like I'm still there.
"How did this happen?"
public class ThisShouldNeverHappenException extends RuntimeException {
public ThisShouldNeverHappenException(Exception cause) {
super(cause);
}
}/ * This should never happen exception. Use in situation that really shouldn't happen...NEVER * * */ public class NeverHappenException extends RuntimeException {
"This should never happen": 823,044 This should never happen: 16,946,357 vs. "This is screwed up": 59 This is screwed up: 876,393
+1