Complete
over 4 years ago

WERETECH-6805

This was addressed in CIQ 3.1.1.

How to debug an unhandled exception

On a fresh Eclipse install on macOS High Sierra with recommended settings (several example apps do build and run), I can't seem to get a strack trace after an unhandled exception (aka app crash). Without that information, it's pretty much impossible to debug an app, so I guess I just missed some setting.

What did I miss?
Former Member
Former Member
  • So what about the real point of this thread? Why isn't the stack always shown in the simulator with exceptions? Without jumping through hoops with try/catch blocks?
  • ekutter, yes you did explicitly mention calls that are "supposed" to return exceptions. My bad. I have to wonder if everyone even catches the exception that I mentioned, as I've heard reports of 3rd party data fields failing when two of them try to connect to the same Stryd power meter.... Exception handling can be nice when you have nested function calls that can fail at several points, all leading to a similar class of error (e.g. "Invalid input".) It avoids having to write the same return value-checking code over and over again. I would've used exceptions in that case, except as I said, it just took too much memory, so I used an archaic global error flag instead. I think indicating (recoverable) errors by return codes vs. exceptions each have pros and cons. It would be very annoying if something like String:find() threw an exception if it couldn't find the provided substring. Of course it's arguable whether that's really an "error". I'm sure something like "Property doesn't exist", as in Jim's example, is much more of a grey area with respect to "is this really an error that deserves an Exception?". Monkey C has some nice features (e.g. symbols), but it's too bad that they all come with significant overhead. I look forward to the day (far in the future) where every Garmin owner has a watch that supports 64+ KB for data fields. jim_m_58 that's actually a great example. Why would "badkey" not exist in that example? It can only be because it's a new settings key that didn't exist in a previous version of the app, right? If you never changed your app settings since the first release, you should never see that exception. If you're just using exceptions to guard against typos or other kinds of mistakes, I would argue that's a bit sloppy. I'm all for bulletproofing code using exceptions (when resources are available), but when it comes to the severely resource-constrained environment of CIQ data fields, I'm with ekutter and I prefer to try to write code that is bulletproof. (Which often fails, at least on the first try, as we all know that's impossible.)
  • A nice thing about try/catch is that you can use it to continue running for something that's recoverable in your app. (no pesky IQ! reports from users!) there's just a simple example var val; try { val=Application.Property.getValue("badkey"); } catch(e) { val=defaultValue; } There are cases I use it for the "this is recoverable" aspect. It could also be used for a user input that throws an exception for some reason. Depending on your code, a single try/catch block could stop the IQ! reports. A "bad XYZ" on the screen instead
  • Yep, totally agree there are different coding styles. And I'm not going to get into a debate here about coding style. But the main one you mention, where a system method you call can throw an exception, is where I explicitly state you should have exception handling. Thankfully those cases in CIQ are few and far between.
  • ekutter, agreed on all points. But TL;DR handling exceptions doesn't necessarily mean you expect to have bugs in your code. --- But, depending on your available memory for code, exceptions can be expected, assuming you wrote your code that way. Errors can be expected too: e.g. invalid user input (obviously this is very rare in the context of CIQ, but I have a data field where it's very relevant) or lack of resources. There are some styles of coding where exceptions are used for just about every kind of error. However, in a resource-constrained CIQ data field, I would prefer to use different ways of reporting errors internally, as exceptions have a bit of code overhead, especially just the code for creating a custom exception class. I saved a lot of code in one data field by using a global error variable :( instead of an exception that could be thrown from anywhere. (This is the same field that can take invalid user input.) Anyway, like it or not, there are some cases in CIQ where exceptions can happen and they are not the result of user error or application bugs. e.g. Toybox::Ant::UnableToAcquireChannelException Thrown if the GenericChannel.initialize() is unable to acquire an ANT channel from the system. This indicates that all available ANT channels are in use. So if you're using an ANT generic channel, you have no choice but to handle exceptions in at least one place, unless you just want your app to crash in that case.