从Function更改上下文返回NULL

时间:2017-02-15 16:25:41

标签: c++ visual-c++ visual-studio-debugging visual-studio-2015

我有三个与此问题相关的课程。我正在为应用程序实现硬件服务。 PAPI(Platform API)是一种硬件服务类,用于跟踪各种硬件接口。我已经实现了一个抽象的HardwareInterface类,以及一个派生它的类,名为HardwareWinUSB。

以下是与我所做的相似的示例。我遗漏了与此问题无关的成员,例如打开USB连接的功能:

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

如果我深入研究PAPI代码,我会看到奇怪的行为。 当我在WritePacket的主体中设置断点时,一切都显得正常。然后我在调试器中“跳过”。从函数调用返回后,我对'this'的引用设置为0x00000000。

发生了什么事?它看起来像是在返回堆栈上推送了一个空值?有没有人见过这样的事情发生过?我是否错误地使用虚拟方法?

修改 在进一步解剖之后,我发现在调用write之前我正在读取,而我正在读取的缓冲区是在本地范围内声明的。当新的读取进入时,它们被推入堆栈,破坏它。下一个名为write的函数将返回到已销毁的堆栈。

2 个答案:

答案 0 :(得分:1)

缓冲区溢出会丢弃堆栈上的返回地址。您似乎正在使用void指针读取和写入数据包,而不会传递显式大小,因此很可能出现一个简单的溢出错误。 Visual Studio编译器具有添加堆栈完整性检查以检测这些类型的错误的选项,但它们并非100%完美。尽管如此,请确保打开它们。

另请注意,Visual Studio调试器偶尔会(但很少)显示this的错误值,尤其是在您尝试调试优化代码时。如果您在方法结束时}处,我不必担心调试器会显示this的奇怪值。

答案 1 :(得分:0)

经过进一步剖析后,我发现在调用write之前我正在读取,而我正在读取的缓冲区是在本地范围内声明的(在read函数中)。

当新的读取进入时,它们被推入堆栈,破坏它。我调用的下一个函数write将返回一个被破坏的堆栈。