C++ 从函数返回将上下文更改为NULL
我有三门课与这个问题有关。我正在为一个应用程序实现一个硬件服务。PAPI(平台API)是一个硬件服务类,用于跟踪各种硬件接口。我实现了一个抽象的HardwareInterface类,以及一个派生它的类HardwareWinUSB 下面是与我所做的类似的例子。我遗漏了似乎与此问题无关的成员,例如打开USB连接的功能:C++ 从函数返回将上下文更改为NULL,c++,visual-c++,visual-studio-debugging,visual-studio-2015,C++,Visual C++,Visual Studio Debugging,Visual Studio 2015,我有三门课与这个问题有关。我正在为一个应用程序实现一个硬件服务。PAPI(平台API)是一个硬件服务类,用于跟踪各种硬件接口。我实现了一个抽象的HardwareInterface类,以及一个派生它的类HardwareWinUSB 下面是与我所做的类似的例子。我遗漏了似乎与此问题无关的成员,例如打开USB连接的功能: class PAPI { HardwareInterface *m_pHardware; PAPI() { m_pHardware = new Ha
class PAPI {
HardwareInterface *m_pHardware;
PAPI() {
m_pHardware = new HardwareWinUSB();
}
~PAPI() {
delete m_pHardware;
}
ERROR_CODE WritePacket(void* WriteBuf)
{
return m_pHardware->write( WriteBuf);
}
};
class HardwareInterface {
virtual ERROR_CODE write( void* WriteBuf) = 0;
};
class HardwareWinUSB : public HardwareInterface
{
ERROR_CODE write( void* Params)
{
// Some USB writing code.
// This had worked just fine before attempting to refactor
// Into this more sustainable hardware management scheme
{
};
我已经为此绞尽脑汁好几个小时了。这是一个奇怪的,可重复的问题,但有时是间歇性的。如果我在更高的上下文中单步执行调试器,事情就会执行得很好。如果我挖得不够深,就会遇到一个错误
Exception thrown at 0x00000000 in <ProjectName.exe>: 0xC0000005: Access violation executing location 0x00000000
在0xC0000005:执行位置0x00000000中的0x00000000处引发异常
如果我深入研究PAPI密码,我会看到奇怪的行为。
当我在WritePacket的主体中设置断点时,一切看起来都正常。然后,我在调试器中执行“跨步”。函数调用返回后,我对“this”的引用设置为0x00000000
发生了什么事?似乎在返回堆栈上推送了空值?以前有人见过这样的事吗?我是否错误地使用了虚拟方法
编辑
在进一步剖析之后,我发现在调用write之前我正在读取,并且我正在读取的缓冲区是在本地范围内声明的。当新的读取进入时,它们被推入堆栈中,破坏了堆栈。下一个名为write的函数将返回到一个已销毁的堆栈。缓冲区溢出会将堆栈上的返回地址丢弃。您似乎正在使用空指针读写数据包,并且没有传递显式大小,因此很可能出现一个简单的溢出错误。VisualStudio编译器可以选择添加堆栈完整性检查来检测这些类型的bug,但它们并不是100%完美的。尽管如此,请确保已将其打开
还请注意,Visual Studio调试器有时(但很少)会为
this
显示错误的值,特别是在您尝试调试优化代码时。如果您在方法末尾的}
,我不必担心调试器显示this
的奇异值。进一步剖析后,我发现在调用write之前我正在读取,并且我正在读取的缓冲区是在本地范围内声明的(在read函数中)
当新的读取进入时,它们被推入堆栈中,破坏了堆栈。我调用的下一个函数write将返回到一个已销毁的堆栈。发生的是代码中的某个错误。一个常见的花园品种错误的结果是“未定义的行为”,你可以观察到的结果肯定是合格的。你只需要找出你的bug是什么。不幸的是,目前还没有按数字绘制的方法来找出并追踪这个bug。如果有,我就失业了…谢谢你的回复,山姆。我知道这是一个bug。我在C++中已经工作了大约三年,还没有看到这样的问题:返回堆栈会像这样被破坏。我希望得到比我更有经验的人的提示,而不是“你的问题是你有问题。”谢谢你的回答,阿德里安。我也有同样的想法,这可能是由缓冲区溢出引起的。所以我检验了这个假设。为此,我将void*参数替换为uint8_t(&Buffer)[PACKET_SIZE],其中PACKET_SIZE是一个定义的常量。这迫使我的代码总是传递特定大小的缓冲区。不幸的是,这似乎没有改变任何事情。我看了一下我复制和设置内存的地方,它们看起来很好。你认为我看到这一点还有其他原因吗?谢谢你在这里分享你的解决方案。如果可能,请将您的回复标记为答案,以便帮助其他社区成员。祝你今天愉快:)