【问题标题】:Why am I getting munmap_chunk(): invalid pointer: error为什么我得到 munmap_chunk(): invalid pointer: error
【发布时间】:2019-10-17 06:03:58
【问题描述】:

因此,当我尝试在 Character 类的“setweapon”函数中“删除”先前分配的武器行为时,我正在做一些作业,突然遇到了这个“无效指针”错误。有人可以指出可能是什么问题吗?


#include <iostream>
using namespace std;

class WeaponBehaviour{
public:
    virtual void useWeapon() = 0;
};

class SwordBehaviour : public WeaponBehaviour {
public:
    void useWeapon()
    {
        cout << "slash slash"<< endl;
    }
};
class BowAndArrowBehavior : public WeaponBehaviour {
public:
    void useWeapon()
    {
        cout << "suss suss"<< endl;
    }
};

class KnifeBehavior : public WeaponBehaviour {
public:
    void useWeapon()
    {
        cout << "chak chakk"<< endl;
    }
};
class AxeBehavior : public WeaponBehaviour {
public:
    void useWeapon()
    {
        cout << "chop chop"<< endl;
    }
};



class Character{
protected:
    WeaponBehaviour* weaponBehaviour;
public:
    Character(){

    }
    ~Character(){
        if(weaponBehaviour != NULL)
        {
            delete weaponBehaviour;
        }
    }
    void setWeapon(WeaponBehaviour* newWeapon)
    {
        if(weaponBehaviour!= NULL )
            delete weaponBehaviour;

        weaponBehaviour = newWeapon;
    }
    void fight()
    {
        weaponBehaviour->useWeapon();
    }
};

class King : public Character
{
public:
    King(){
        setWeapon(new SwordBehaviour);
    }
};

class Queen : public Character
{
public:
    Queen(){
        setWeapon(new KnifeBehavior);
    }
};

int main() {
    King king ;
    king.fight();
    Queen queen ;
    queen.fight();
    queen.setWeapon(new AxeBehavior);
    queen.fight();
    return 0;
}

我得到的错误是

* `Cpp-design-patters/Debug/strategy-pattern' 中的错误:munmap_chunk():无效指针:0x0000000000400f50 * ======= 回溯:========= /lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7ff746d757e5] /lib/x86_64-linux-gnu/libc.so.6(cfree+0x1a8)[0x7ff746d82698]

【问题讨论】:

  • 您应该尝试使用调试器。这是解决此类问题的宝贵工具。也编译警告。 WeaponBehaviour 中没有虚拟析构函数,因此代码中的删除是 UB。
  • 如果我正确阅读了该回溯(其格式有点混乱),那么这与您的代码相去甚远。您的代码(您应该将其带到 codereview.stackexchange.com,顺便说一句,还有很多需要改进的地方)看起来不会对我造成这种影响。唯一明显的错误是缺少虚拟析构函数。
  • @PaulRooney 感谢您的提示,问题是因为没有使用虚拟析构函数添加它解决了问题。
  • 好酷。我添加了它,但仍然有段错误。您应该将 -Wall -Wextra -pedantic 标志传递给 GCC 并传递 -g 以包含调试符号。有了这个 GCC 就 dtor 发出警告。
  • 你永远不会将weaponBehaviour 初始化为NULL,它有一个不确定的值,可能not NULL,所以你会尝试delete 一些你从来没有的东西new'd

标签: c++


【解决方案1】:

您需要将weaponBehaviour 初始化为nullptr 否则weaponBehaviour 将有一个未定义(可能非空)的值并且

if(weaponBehaviour!= NULL)
  delete weaponBehaviour;

将传递 if 语句并删除无效指针。

您的编译器还应该警告您(如果您已打开警告)您有一个没有虚拟析构函数的虚拟类。当通过WeaponBehaviour 指针删除对象时,这会导致未定义的行为。 WeaponBehaviour 的正确声明是:

class WeaponBehaviour{
public:
    virtual WeaponBehaviour() {}
    virtual void useWeapon() = 0;
};

这不会导致您的代码出现问题(目前),但您应该注意rule of three/five

以上所有问题都可以通过使用std::unique_ptr 来解决,并使您的代码更简单、更安全:

#include <iostream>
#include <memory>

class WeaponBehaviour{
public:
    virtual ~WeaponBehaviour(){}
    virtual void useWeapon() = 0;
};

class SwordBehaviour : public WeaponBehaviour {
public:
    void useWeapon()
    {
        std::cout << "slash slash\n";
    }
};
class BowAndArrowBehavior : public WeaponBehaviour {
public:
    void useWeapon()
    {
        std::cout << "suss suss\n";
    }
};

class KnifeBehavior : public WeaponBehaviour {
public:
    void useWeapon()
    {
        std::cout << "chak chakk\n";
    }
};
class AxeBehavior : public WeaponBehaviour {
public:
    void useWeapon()
    {
        std::cout << "chop chop\n";
    }
};



class Character{
protected:
    std::unique_ptr<WeaponBehaviour> weaponBehaviour;
public:
    void setWeapon(std::unique_ptr<WeaponBehaviour>&& newWeapon)
    {
        weaponBehaviour = std::move(newWeapon);
    }
    void fight()
    {
        weaponBehaviour->useWeapon();
    }
};

class King : public Character
{
public:
    King(){
        setWeapon(std::make_unique<SwordBehaviour>());
    }
};

class Queen : public Character
{
public:
    Queen(){
        setWeapon(std::make_unique<KnifeBehavior>());
    }
};

int main() {
    King king ;
    king.fight();
    Queen queen ;
    queen.fight();
    queen.setWeapon(std::make_unique<AxeBehavior>());
    queen.fight();
    return 0;
}

【讨论】:

    猜你喜欢
    • 2021-10-03
    • 1970-01-01
    • 2011-02-11
    • 2017-07-16
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    • 2020-07-23
    • 1970-01-01
    相关资源
    最近更新 更多