I'm using Boost for some in-house codes. In main(), I would like to catch and log all boost::exceptions before exiting the program.
How do I catch boost::exceptions and retrieve the exception information as a string, for logging?
I recommend that you take a look at boost::diagnostic_information.
Here is an example for you. It is by no means complete and will take some customization to get it to do exactly what you want.
void main()
{
try
{
// Your code that can throw.
}
catch (const boost::exception& ex)
{
// Output some debug information.
std::cerr << boost::diagnostic_information(ex) << std::endl;
// Here we can choose to perform some graceful-shutdown activities,
// and/or rethrow the exception, triggering a call to std::terminate().
throw; // Rethrow.
}
catch (const std::exception& ex)
{
// Let's do the same for std::exception just for comparison.
std::cerr << ex.what() << std::endl;
throw; // Rethrow.
}
}
Where you will probably need to customize this:
Rethrowing in the main will trigger a std::terminate(). You might want to perform some tasks that more gracefully shutdown your code.
std::cerr might not be a great place to send this sort of information for you. Perhaps you want to log it to file. Or perhaps you might want to redirect std::cerr to a file.
Your code may have a chance of throwing something that is not a boost::exception or a std::exception. Maybe you want a catch all for that: catch (...)
Keep in mind that this is try-catch block only comes into play on the main thread of your application. You will have to do something similar in the entrypoints of any other threads that might throw an exception that is not handled.
This is no replacement for proper exception handling throughout your entire application.
Related
I'm writing a Modbus client program using Qt5 and the QModbusTcpClient class. Here the code I'm using for open a connection and read something:
QModbusClient *_modbus;
bool ModbusMaster::open(QString host, int port)
{
// Disconnect and delete any existing instance
if (_modbus)
{
_modbus->disconnectDevice();
delete _modbus;
}
// Create and open the new connection
_modbus = new QModbusTcpClient(this);
_modbus->setConnectionParameter(QModbusDevice::NetworkPortParameter, port);
_modbus->setConnectionParameter(QModbusDevice::NetworkAddressParameter, host);
_modbus->setTimeout(250);
_modbus->setNumberOfRetries(1);
return _modbus->connectDevice();
}
bool ModbusMaster::read(QModbusDataUnit::RegisterType type, int startAddress, quint16 count)
{
if (!_modbus) return false;
if (_modbus->state() != QModbusDevice::ConnectedState) return false;
QModbusDataUnit req(type, startAddress, count);
if (auto *reply = _modbus->sendReadRequest(req, _id))
{
if (!reply->isFinished()) connect(reply, &QModbusReply::finished, this, &ModbusMaster::readReady);
else delete reply;
return true;
}
return false;
}
void ModbusMaster::readReady()
{
auto reply = qobject_cast<QModbusReply *>(sender());
if (!reply) return;
reply->deleteLater();
if (reply->error() == QModbusDevice::NoError)
{
// do something
}
else if (reply->error() == QModbusDevice::ProtocolError)
{
qDebug() << QString("Read response error: %1 (Mobus exception: 0x%2)").
arg(reply->errorString()).
arg(reply->rawResult().exceptionCode(), -1, 16);
} else {
qDebug() << QString("Read response error: %1 (code: 0x%2)").
arg(reply->errorString()).
arg(reply->error(), -1, 16);
}
}
Sometimes when I read something from the remote device it happens the device returns the exception 0x5. Reading the official Modbus documentation, at page 48 I read:
Specialized use in conjunction with programming
commands.
The server has accepted the request and is
processing it, but a long duration of time will be
required to do so. This response is returned to
prevent a timeout error from occurring in the
client. The client can next issue a Poll Program
Complete message to determine if processing is
completed.
[bold is mine]
I cannot find a description of this "Poll Program Complete message" that seems I must use to handle the exception 0x5.
Did I search wrong? Is there another way to handle this exception?
It depends on type of an equipment, you are working with. You just have to follow the logic, described in equipment mans for this particular exception.
In general there is no special 'Program Complete' event. That means, as it is written for 0x5 - "Specialized use in conjunction with programming commands.". So you just have to poll (read) some flag from your device meaning the internal process in device, which caused this exception, is complete.
Just as an example, I've met with such exception in relay protection device, which issued it when it has been in a process of writing a disturbance record. I had just to check for that record readiness in some time.
I saw many people wrote like:
try {
//something
}
catch (IOException e){
throw new SystemException("IO Error", e);
}
I got "Cannot instantiate the type SystemException" error and it seems SystemException is a abstract class, how can I able to throw it?
Yes, it is an abstract class and that means that it does not make sense to construct an object of type SystemException. It is recommended to use more meaningful exceptions types.
You have mentioned IOException in your code. This means an exception related to an I/O operation and the catcher can act accordingly (maybe a special log level, some I/O cleanup etc.).
In your particular case, I think you should change it to:
try {
//something
}
catch (IOException e) {
// log exception info and other context information here
// e.g. e.printStackTrace();
// just rethrowing the exception (call stack is still there)
throw e;
}
P.S. Quite offtopic, but coming from .NET world I have found about the subtle difference between throw ex; in C# vs. Java.
I have few similar methods and there calls as follows :
methodThrowingException() throws NullPointerException, InterruptedException, TimeoutException {
<method logic>
}
Calling class :
try{
methodThrowingExceptions();
<some other logic>
}
catch (NullPointerException npx) {
npx.printStackTrace();
log more details...
}
catch (InterruptedException inx) {
inx.printStackTrace();
log more details...
}
catch (TimeoutException tox) {
tox.printStackTrace();
log more details..
}
How (if) can I put all of these three in one Custom Exception?
Other than (1) is there a way to optimise the code so that I need not write the entire same statements for multiple methods?
Since Java 7, you can use a multi-catch block:
catch (NullPointerException | InterruptedException | TimeoutException e) {
e.printStackTrace();
log more details...
}
That said, you should never catch NullPointerException: that is a bug, and if it happens, the exception should bubble up. You can't reasonably expect a NPE to happen.
In addition, doing the same thing for an InterruptedException as for the other exceptions is also very dubious. When catching an InterruptedException, you should reset the interrupted flag on the current thread, and stop what you're doing ASAP.
"Only the types that are inherited from the Throwable class can be thrown".
Could anybody explain me. Why not every type are throwable? If in doc there no mention about function can throw exception, it's mean that it do not have exception?
For example I thought that next try-catch block would work. But it is not.
try
{
writeln("(((((((((");
latestdtonpage = dts.sort!((a,b) => a>b).front; //latest date-time. from page.
}
catch(Exception e)
{
writeln("Can't select the latest Date from parsed date");
writeln(e);
}
But output in case of exception is next (no exception text):
(((((((((
core.exception.AssertError#C:\D\dmd2\windows\bin\..\..\src\phobos\std\array.d(73
9): Attempting to fetch the front of an empty array of DateTime
----------------
0x0051C4C9 in _d_assert_msg
0x00468E78 in pure nothrow ref #property #nogc #safe std.datetime.DateTime std.r
ange.__T11SortedRangeTAS3std8datetime8DateTimeS473app19StackOverflowParser5parse
MFAyaZ9__lambda2Z.SortedRange.front() at C:\D\dmd2\windows\bin\..\..\src\phobos\
std\range.d(8418)
0x0044F908 in void app.StackOverflowParser.parse(immutable(char)[]) at D:\code\T
rendoMetr\source\app.d(173)
0x0044F700 in app.StackOverflowParser app.StackOverflowParser.__ctor(app.DBConne
ct) at D:\code\TrendoMetr\source\app.d(150)
0x0044F199 in _Dmain at D:\code\TrendoMetr\source\app.d(33)
0x0052EDCA in D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv
0x0052ED9F in void rt.dmain2._d_run_main(int, char**, extern (C) int function(ch
ar[][])*).runAll()
0x0052ECB5 in _d_run_main
0x00470198 in main
0x005667D1 in mainCRTStartup
0x76D1336A in BaseThreadInitThunk
0x772A9F72 in RtlInitializeExceptionChain
0x772A9F45 in RtlInitializeExceptionChain
Error executing command run: Program exited with code 1
How I can throw exception in this code?
Your code throws an AssertError, indicating that dts.sort!((a,b) => a>b) is empty, and you shouldn't call .front on it. Instead, query .empty first, and act accordingly when it's true.
AssertError inherits from Error which in turn inherits from Throwable but not from Exception. So catch(Exception e) doesn't catch it. And you should not catch Errors anyway, as they indicate that the program is in an unrecoverable error-state.
AssertError in particular signals a logic bug in your program. Here: calling .front on an empty range. Don't catch AssertError, but fix your code instead.
I am now learning Intel pin, I write the following codes in main function of my pintool.
try
{
throw std::exception("test daniel");
}
catch (std::exception& e)
{
printf(e.what());
}
Run it( pin.exe -t Test.dll -- calc.exe), but it just crashed, this is definitely due to an uncaught exception.
But I wonder why my "catch" code failed.
Anyone know the reason, or how to catch exception in pintool?
Here is how thrown exceptions should be catched in a pintool, assuming you have all the mandatory compile options. It should be noted that this simple pintool does not do anything beside catching exceptions thrown by pin or the tool (not the application).
You will note that the registration of the exception handler function occures before the PIN_StartProgram() function, otherwise exceptions will be ignored.
Finally, although it is not mentioned in the documentation, I would expect that exceptions thrown after the call to PIN_AddInternalExceptionHandler() and before PIN_StartProgram() be not catched by the handler. I would instead expect the handler to catch exceptions thrown after PIN_StartProgram(), but again, it is not mentioned in the documentation.
//-------------------------------------main.cpp--------------------------------
#include "pin.h"
#include <iostream>
EXCEPT_HANDLING_RESULT ExceptionHandler(THREADID tid, EXCEPTION_INFO *pExceptInfo, PHYSICAL_CONTEXT *pPhysCtxt, VOID *v)
{
EXCEPTION_CODE c = PIN_GetExceptionCode(pExceptInfo);
EXCEPTION_CLASS cl = PIN_GetExceptionClass(c);
std::cout << "Exception class " << cl;
std::cout << PIN_ExceptionToString(pExceptInfo);
return EHR_UNHANDLED ;
}
VOID test(TRACE trace, VOID * v)
{
// throw your exception here
}
int main(int argc, char *argv[])
{
// Initialize PIN library. This was apparently missing in your tool ?
PIN_InitSymbols();
if( PIN_Init(argc,argv) )
{
return Usage();
}
// Register here your exception handler function
PIN_AddInternalExceptionHandler(ExceptionHandler,NULL);
//register your instrumentation function
TRACE_AddInstrumentFunction(test,null);
// Start the program, never returns...
PIN_StartProgram();
return 0;
}