在 Visual Studio 调试器外部运行程序时如何调试访问冲突?
设置实时调试选项并运行独立程序,直到发生访问冲突。 然后,在”访问冲突”对话框中,你可以单击”取消”以启动调试器 。
如何调试 C++ 访问冲突?
如果在取消引用多个指针的代码行上出现访问冲突,则可能很难辨别引起访问冲突的指针。 在 Visual Studio 中,异常对话框显式命名导致访问冲突的指针。
例如,以下代码中,将出现访问冲突:
#include <iostream>
using namespace std;
class ClassC {
public:
void printHello() {
cout << "hello world";
}
};
class ClassB {
public:
ClassC* C;
ClassB() {
C = new ClassC();
}
};
class ClassA {
public:
ClassB* B;
ClassA() {
// Uncomment to fix
// B = new ClassB();
}
};
int main() {
ClassA* A = new ClassA();
A->B->C->printHello();
}
如果在 Visual Studio 中运行此代码,你将看到以下异常对话框:
如果无法确定该指针为何导致访问冲突,请对代码进行跟踪,以确保导致该问题的指针被正确处理。 如果它作为参数传递,请确保正确传递且未意外创建浅表副本。 然后为有问题的指针创建一个数据断点,以确保它没有在程序的其他地方被修改,从而验证这些值没有在程序的某个地方被无意地更改。 有关数据断点的详细信息,请参阅 使用断点中的数据断点部分。
如何查明指针是否损坏了内存地址?
检查堆损坏。 大多数内存损坏是由堆损坏引起的。 尝试使用 Global Flags Utility (gflags.exe) 或 pageheap.exe。 请参阅 /windows-hardware/drivers/debugger/gflags-and-pageheap。
若要查找修改内存地址的位置:
在 0x00408000 处设置一个数据断点。 请参阅设置数据更改断点(仅限本机 C++)。
当命中断点时,使用“内存”窗口,以查看从 0x00408000 开始的内存内容。 有关详细信息,请参阅内存窗口。
如何查明谁在传递错误的参数值?
若要解决此问题,请执行以下操作:
在函数的开始处设置一个位置断点。
右键单击该断点并选择“条件”。
在“断点条件”对话框中,单击“条件”复选框 。 请参阅高级断点。
在文本框中输入一个表达式,例如
Var==3
,此处Var
是包含错误值的参数名称,3
是传给此参数的错误值。选择“为真”单选按钮,单击“确定”按钮 。
现在再次运行程序。 当
Var
参数的值为3
时,断点导致程序在函数开始处暂停。然后可以使用“调用堆栈”窗口查找调用函数并定位到其源代码。 有关详细信息,请参阅如何:使用“调用堆栈”窗口。
当一个函数被调用数百次时,如何确定哪次调用失败了?
示例:程序在调用某函数(如 CnvtV
)时失败。 失败以前该程序可能已调用了该函数数百次。 如果我在 CnvtV
上设置一个位置断点,程序在每次调用该函数时都停止,而我不希望这样。 我不知道什么条件导致调用失败,所以无法设置条件断点。 我该怎么办?
在函数上设置断点时可以将“命中次数”字段设置为一个大到永远无法达到的值。 在这种情况中,由于你确信函数 CnvtV
被调用了数百次,所以将“命中次数”设置为 1000 或更高。 然后运行程序,等待调用失败。 程序失败后,打开“断点”窗口并查看断点列表。 将显示您在 CnvtV
上设置的断点,其后跟着命中次数和剩余迭代次数:
CnvtV(int) (no condition) when hit count is equal to 1000 (currently 101)
现在您知道函数在第 101 次调用时失败。 如果重置断点,将命中次数设置为 101,然后再次运行程序,程序将在导致 CnvtV
调用失败的位置停止所有该调用。
可以在哪里查阅 Win32 错误代码?
默认系统安装的 INCLUDE 目录中的 WINERROR.H 包含 Win32 API 函数的错误代码定义。
可以通过在“监视”窗口或“快速监视”对话框中键入错误代码来查阅该代码 。 例如:
0x80000004,hr
如何在逐句执行应用代码时保持焦点?
示例:我的程序存在窗口激活问题。 用调试器逐句通过程序时,因为程序不断失去焦点,所以妨碍了再现问题。 是否有方法可以避免失去焦点?
如果有另一台计算机,请使用远程调试。 可以在远程计算机上运行您的程序,而在主机上运行调试器。 有关详细信息,请参阅如何:选择远程计算机。
如何调试 Windows API 函数?
若要在加载了 NT 符号的 Windows API 函数中设置断点: