代码之家  ›  专栏  ›  技术社区  ›  Tony

调用方法时发生访问冲突异常

  •  4
  • Tony  · 技术社区  · 16 年前

    我有个奇怪的问题。假设我有一个 方法。在某些情况下,这个类的实例应该调用其中一个方法。大多数情况下,该阶段不会出现问题,但有时会发现无法调用虚拟方法,因为指向该方法的指针为NULL(如VS所示),因此会发生内存访问冲突异常。怎么会这样?

    void MyClass::FirstMethod() const { /* Do stuff */ }
    void MyClass::SecondMethod() const
    {
        // This is where exception occurs, 
        // description of this method during runtime in VS looks like 0x000000
        FirstMethod(); 
    }
    

    不涉及构造器或析构函数。

    7 回复  |  直到 14 年前
        1
  •  6
  •   Lightness Races in Orbit    14 年前

    堆损坏可能是一个候选。对象中的v-table指针易受攻击,它通常是对象中的第一个字段。某类其他对象的缓冲区溢出恰好与该对象相邻,将擦除v-table指针。对虚拟方法的调用(通常是在很久以后)将失败。

        2
  •  2
  •   Steve Jessop    16 年前

    可能是从一个本身没有该函数的基类的构造函数调用函数(直接或间接)。

    reinterpret_cast 当涉及多个继承时,指针的类型)并且您正在查看vtable以查找错误的类。

    你可能(但不太可能)把vtable弄坏了。

        3
  •  1
  •   JaredPar    16 年前

        4
  •  1
  •   Mark B    16 年前

    是否可能在SecondMethod的处理过程中删除了“this”指针?

    另一种可能性是SecondMethod实际上是在前面用一个无效的指针调用的,并且它恰好在嵌套函数调用之前工作(通过未定义的行为),然后调用失败。如果您能够添加打印代码,请检查“this”和/或正在使用的其他指针是否类似于0xcdcdcdcdcd或0xfdfdfd,这些指针在执行这些方法期间的不同位置。这些值(我相信)是由VS在内存alloc/dealloc上使用的,这可能是在调试模式下编译时工作的原因。

        5
  •  0
  •   KPexEA    16 年前

    如果你能一直让它在同一个地方崩溃,并且能找出空指针从何处加载,那么我建议使用调试器,并在该内存位置的“write”上设置一个断点,一旦触发断点,那么很可能你正在查看实际导致损坏的代码。

        6
  •  0
  •   user215054 user215054    16 年前

    如果只有当Studio无法显示方法地址时才会发生内存访问冲突,那么可能是由于缺少调试信息造成的。您可能正在调试使用发行版(非调试)编译器/链接器标志编译的代码。

    请尝试在项目的C++属性中启用一些调试信息,重新构建并重新启动调试器。如果有帮助的话,你会看到所有正常的可追踪的东西,比如堆栈、变量等等。

        7
  •  0
  •   Shing Yip    16 年前

    如果您的this指针为空,则不太可能发生损坏。除非你把你不该有的记忆归零。

    你没有说你是调试调试(未优化)还是发布(优化)版本。通常,如果不需要这个指针,在发行版中构建优化器将删除它。因此,如果您正在调试优化的构建,将此指针视为0并不意味着什么。你必须依靠拆装配来告诉你发生了什么。如果无法在调试版本中重现问题,请尝试在发布版本中关闭优化。调试优化生成时,调试程序集不是C++。

    如果已经在调试未优化的生成,请确保在花费太多时间调试损坏的映像之前有一个干净的重建。调试构建通常是增量链接的,增量链接器会产生这样的问题。如果您使用干净的构建运行调试构建,但仍然无法找出哪里出了问题,请发布堆栈转储和更多代码。我相信我们能帮你弄清楚。

    推荐文章