在 MS Visual C++ 中调试未处理异常的正确方法
Right way to debug unhandled exception in MS Visual C++
在 Microsoft Visual Studio C++(本机 c++,Visual Studio 2015)中调试未知未处理异常的正确方法是什么。
今天收到异常(正文:Exception thrown: read access violation. this was 0x4.
):
按下 "Break" 按钮后显示的代码只是来自标准 Qt framework header qscopedpointer.h
:
的代码
现在我不知道这个问题的原因是什么。通常这没问题,但我知道我有 运行 项目,它总是在 VS 2012 中纠正 运行,现在我什至不确定这是一个真正的错误还是我只需要取消选中 "Break when this exception type is thrown"。
我无法"Step out",查看调用堆栈也无法理解问题:
正文:
Qt5Cored.dll!QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> >::data() Line 135 C++
Qt5Cored.dll!qGetPtrHelper<QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> > >(const QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> > & p) Line 1014 C++
Qt5Cored.dll!QWinOverlappedIoNotifier::d_func() Line 60 C++
Qt5Cored.dll!QWinOverlappedIoNotifier::waitForAnyNotified(int msecs=1) Line 358 C++
Qt5SerialPortd.dll!QSerialPortPrivate::waitForNotified(int msecs=1) Line 588 C++
Qt5SerialPortd.dll!QSerialPortPrivate::waitForReadyRead(int msecs=1) Line 251 C++
Qt5SerialPortd.dll!QSerialPort::waitForReadyRead(int msecs=1) Line 1309 C++
MyProject.exe!UsualSep::send_cmd_and_receive_answer(const QByteArray & ba={...}, QByteArray & ans={...}, int nread=2) Line 797 C++
MyProject.exe!UsualSep::isAvailable(bool & avbl=false) Line 204 C++
MyProject.exe!UsualSep::on_workThread_started() Line 80 C++
MyProject.exe!QtPrivate::FunctorCall<QtPrivate::IndexesList<>,QtPrivate::List<>,void,void (__thiscall UsualSep::*)(void)>::call(void(UsualSep::*)() f=0x00eb172b, UsualSep * o=0x007838d8, void * * arg=0x02bff91c) Line 501 C++
MyProject.exe!QtPrivate::FunctionPointer<void (__thiscall UsualSep::*)(void)>::call<QtPrivate::List<>,void>(void(UsualSep::*)() f=0x00eb172b, UsualSep * o=0x007838d8, void * * arg=0x02bff91c) Line 520 C++
MyProject.exe!QtPrivate::QSlotObject<void (__thiscall UsualSep::*)(void),QtPrivate::List<>,void>::impl(int which=1, QtPrivate::QSlotObjectBase * this_=0x029ee9d8, QObject * r=0x007838d8, void * * a=0x02bff91c, bool * ret=0x00000000) Line 143 C++
Qt5Cored.dll!QtPrivate::QSlotObjectBase::call(QObject * r=0x007838d8, void * * a=0x02bff91c) Line 124 C++
Qt5Cored.dll!QMetaObject::activate(QObject * sender=0x029ee9a0, int signalOffset=3, int local_signal_index=0, void * * argv=0x00000000) Line 3720 C++
Qt5Cored.dll!QMetaObject::activate(QObject * sender=0x029ee9a0, const QMetaObject * m=0x670e5db0, int local_signal_index=0, void * * argv=0x00000000) Line 3595 C++
Qt5Cored.dll!QThread::started(QThread::QPrivateSignal __formal={...}) Line 156 C++
Qt5Cored.dll!QThreadPrivate::start(void * arg=0x029ee9a0) Line 384 C++
ucrtbased.dll!774f8968() Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for ucrtbased.dll]
ucrtbased.dll!774f867b() Unknown
kernel32.dll!74fc336a() Unknown
ntdll.dll!77169902() Unknown
ntdll.dll!771698d5() Unknown
我的主要问题不是在这种特殊情况下该怎么做,而是调试此类异常的一般方法是什么。
如果 异常在调用堆栈中的某处有一个处理程序,它 可能 可以让它继续,无论如何。但是,请查看以确保您了解发生了什么。
如果调用堆栈指向您的代码,请从那里开始。我想,在这种情况下,"MyProject.exe!UsualSep::send_cmd_and_receive_answer..." 这最终如何尝试获取数据 d
?你认为你在这里设置了吗?
我的一般方法是尝试将问题缩小到一个小的独立函数并将其包装在一个测试中,您可以 运行 自动重复该问题。然后尝试修复它。也许您需要尝试 isNull
作为代码中某处的检查?
如果您检查 "break when this exception type is thrown" 那么我猜想在下一次调试 运行 时,您将在抛出异常时打开调试器,这很可能会告诉您问题所在。
如果你处理异常当然它不再一定是一个错误。通过在 main 的 try 块中处理异常,然后向下钻取以准确计算出程序的哪一部分抛出它,您可以进行一些困难的调试。
Qt 中可能存在错误,而不是您自己的代码。如果是这样,它很可能是一些相当晦涩的东西——Qt 已经过大多数一般现实世界使用的测试——但很难找到。但是,堆栈跟踪表明您的函数 send_cmd_and_receive_answer() 有问题。很可能它是用它不拥有的内存调用 Qt,或者换句话说,它向它传递了一个野指针。
在 Microsoft Visual Studio C++(本机 c++,Visual Studio 2015)中调试未知未处理异常的正确方法是什么。
今天收到异常(正文:Exception thrown: read access violation. this was 0x4.
):
按下 "Break" 按钮后显示的代码只是来自标准 Qt framework header qscopedpointer.h
:
现在我不知道这个问题的原因是什么。通常这没问题,但我知道我有 运行 项目,它总是在 VS 2012 中纠正 运行,现在我什至不确定这是一个真正的错误还是我只需要取消选中 "Break when this exception type is thrown"。
我无法"Step out",查看调用堆栈也无法理解问题:
正文:
Qt5Cored.dll!QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> >::data() Line 135 C++
Qt5Cored.dll!qGetPtrHelper<QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> > >(const QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> > & p) Line 1014 C++
Qt5Cored.dll!QWinOverlappedIoNotifier::d_func() Line 60 C++
Qt5Cored.dll!QWinOverlappedIoNotifier::waitForAnyNotified(int msecs=1) Line 358 C++
Qt5SerialPortd.dll!QSerialPortPrivate::waitForNotified(int msecs=1) Line 588 C++
Qt5SerialPortd.dll!QSerialPortPrivate::waitForReadyRead(int msecs=1) Line 251 C++
Qt5SerialPortd.dll!QSerialPort::waitForReadyRead(int msecs=1) Line 1309 C++
MyProject.exe!UsualSep::send_cmd_and_receive_answer(const QByteArray & ba={...}, QByteArray & ans={...}, int nread=2) Line 797 C++
MyProject.exe!UsualSep::isAvailable(bool & avbl=false) Line 204 C++
MyProject.exe!UsualSep::on_workThread_started() Line 80 C++
MyProject.exe!QtPrivate::FunctorCall<QtPrivate::IndexesList<>,QtPrivate::List<>,void,void (__thiscall UsualSep::*)(void)>::call(void(UsualSep::*)() f=0x00eb172b, UsualSep * o=0x007838d8, void * * arg=0x02bff91c) Line 501 C++
MyProject.exe!QtPrivate::FunctionPointer<void (__thiscall UsualSep::*)(void)>::call<QtPrivate::List<>,void>(void(UsualSep::*)() f=0x00eb172b, UsualSep * o=0x007838d8, void * * arg=0x02bff91c) Line 520 C++
MyProject.exe!QtPrivate::QSlotObject<void (__thiscall UsualSep::*)(void),QtPrivate::List<>,void>::impl(int which=1, QtPrivate::QSlotObjectBase * this_=0x029ee9d8, QObject * r=0x007838d8, void * * a=0x02bff91c, bool * ret=0x00000000) Line 143 C++
Qt5Cored.dll!QtPrivate::QSlotObjectBase::call(QObject * r=0x007838d8, void * * a=0x02bff91c) Line 124 C++
Qt5Cored.dll!QMetaObject::activate(QObject * sender=0x029ee9a0, int signalOffset=3, int local_signal_index=0, void * * argv=0x00000000) Line 3720 C++
Qt5Cored.dll!QMetaObject::activate(QObject * sender=0x029ee9a0, const QMetaObject * m=0x670e5db0, int local_signal_index=0, void * * argv=0x00000000) Line 3595 C++
Qt5Cored.dll!QThread::started(QThread::QPrivateSignal __formal={...}) Line 156 C++
Qt5Cored.dll!QThreadPrivate::start(void * arg=0x029ee9a0) Line 384 C++
ucrtbased.dll!774f8968() Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for ucrtbased.dll]
ucrtbased.dll!774f867b() Unknown
kernel32.dll!74fc336a() Unknown
ntdll.dll!77169902() Unknown
ntdll.dll!771698d5() Unknown
我的主要问题不是在这种特殊情况下该怎么做,而是调试此类异常的一般方法是什么。
如果 异常在调用堆栈中的某处有一个处理程序,它 可能 可以让它继续,无论如何。但是,请查看以确保您了解发生了什么。
如果调用堆栈指向您的代码,请从那里开始。我想,在这种情况下,"MyProject.exe!UsualSep::send_cmd_and_receive_answer..." 这最终如何尝试获取数据 d
?你认为你在这里设置了吗?
我的一般方法是尝试将问题缩小到一个小的独立函数并将其包装在一个测试中,您可以 运行 自动重复该问题。然后尝试修复它。也许您需要尝试 isNull
作为代码中某处的检查?
如果您检查 "break when this exception type is thrown" 那么我猜想在下一次调试 运行 时,您将在抛出异常时打开调试器,这很可能会告诉您问题所在。
如果你处理异常当然它不再一定是一个错误。通过在 main 的 try 块中处理异常,然后向下钻取以准确计算出程序的哪一部分抛出它,您可以进行一些困难的调试。
Qt 中可能存在错误,而不是您自己的代码。如果是这样,它很可能是一些相当晦涩的东西——Qt 已经过大多数一般现实世界使用的测试——但很难找到。但是,堆栈跟踪表明您的函数 send_cmd_and_receive_answer() 有问题。很可能它是用它不拥有的内存调用 Qt,或者换句话说,它向它传递了一个野指针。