【问题标题】:Invalid address specified to RtlValidateHeap when deleting pointer to derived class删除指向派生类的指针时指定给 RtlValidateHeap 的地址无效
【发布时间】:2016-07-13 18:26:08
【问题描述】:

我正在处理的 C++ 项目中存在多态性问题。我有一个名为 State 的基类和一个派生的 TestState 类。我正在尝试从 State 指针调用在派生类中重写的虚函数。调用了虚函数,但是在删除指针时出现以下错误:

Invalid address specified to RtlValidateHeap( 00FF0000, 0018FD74 )

在搜索其他答案后,我已经能够理解这意味着堆已损坏,但我找到的解决方案都没有为我工作。

这是我正在运行的代码:

int main()
{
    TestState test;

    State *state = new State();
    state = &test;

    state->Init();

    delete state; 
}

状态.h

#pragma once

#include <iostream>

class State
{
public:
    State();
    virtual ~State();

    virtual void Init();
    virtual void Reinit();
    virtual void Deinit();
};

状态.cpp

#include "State.h"

State::State()
{
}

State::~State()
{
    std::cout << "Destroying State!" << std::endl;
}

void State::Init()
{
    std::cout << "Initialized State!" << std::endl;
}

void State::Deinit()
{
}

void State::Reinit()
{
}

TestState.h

#pragma once
#include "State.h"
#include <iostream>

class TestState : public State
{
public:
    TestState();
    ~TestState();

    void Init();
    void Deinit();
    void Reinit();
};

TestState.cpp

#include "TestState.h"

TestState::TestState()
{
}

TestState::~TestState()
{
    std::cout << "Destroying TestState!" << std::endl;
}

void TestState::Init()
{
    std::cout << "Initialized TestState!" << std::endl;
}

void TestState::Deinit()
{
}

void TestState::Reinit()
{
}

State 和 TestState 的析构函数都会在指针被删除时调用。

提前致谢。

【问题讨论】:

  • 您缺少复制/移动构造函数/赋值运算符!
  • 抱歉,我是 C++ 新手,你能解释一下为什么在这种情况下我需要它们吗?
  • 它被称为“3 规则”或“5 规则”。如果定义 any of:析构函数、复制/移动构造函数、复制/移动赋值运算符,则必须定义它们的 all。请注意,已删除的定义仍然很重要(例如,对于仅移动类)。

标签: c++ pointers memory polymorphism heap-memory


【解决方案1】:

因为您正在删除堆栈中的某些内容。当您将指针分配给对局部变量的引用时,您将指针分配给堆栈中分配的实体。不能使用用于堆变量的“删除”来删除它。此外,您还泄漏了新分配的内容。

    TestState test;

    State *state = new State();
    state = &test; //Now it points to the test which is in the stack

    state->Init();

    delete state; //Delete something in the stack. Not good.

这样的东西应该会更好。

   TestState test;

   State *state = &test;

   state->Init();

【讨论】:

  • 我试过这个,但它仍然给了我同样的错误,有什么想法吗?
  • 在 VS2015 中为我工作,(在这种情况下,不需要删除,因为您没有在堆上分配任何东西)。
  • 啊,对不起。忘记删除删除。现在可以了!
【解决方案2】:

即使您的特定问题的解决方案很简单(即您试图删除堆栈分配的变量,就好像它是堆分配的一样),我想将我的解决方案发布到我神秘的 RtlValidateHeap 断言。

事实证明,我正在处理的代码在“运行时库”的项目之间具有混合设置(在项目属性中,在 C/C++ -> 代码生成下)。该应用程序具有“多线程调试”,DLL 具有“多线程调试 DLL”。它们都需要设置为相同的东西。

如果混合使用 DLL 和非 DLL 运行时库,最终会产生两个独立的堆,并且无法从使用另一个运行时库的代码中删除分配在一个运行时库下的对象。你最终会得到神秘的 RtlValidateHeap 断言。

希望这对其他人有所帮助。

【讨论】:

    【解决方案3】:

    这就是共享指针的用途 :) The Cherno 在youtube 上有一个非常好的智能指针视频。

    这应该可以解决问题,将您的主要内容更改为:

    #include "TestState.h"
    #include "State.h"
    #include <memory>
    
    int main()
    {
       {
       std::shared_ptr<TestState> test = std::make_shared<TestState>();
        
       std::shared_ptr<TestState> state = test;
    
       state->Init();
       }
       //delete state; 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-04
      • 2023-03-17
      • 2015-10-15
      • 1970-01-01
      • 1970-01-01
      • 2012-01-05
      • 1970-01-01
      相关资源
      最近更新 更多