【问题标题】:delete on pointer (*&) to base class with virtual destructor c++使用虚拟析构函数c ++删除指向基类的指针(*&)
【发布时间】:2020-12-27 22:48:36
【问题描述】:

所以,我有一个游戏服务器在一个非常旧的系统(2006-2007)上运行,当玩家登录时创建一个玩家对象,创建一个怪物时创建一个怪物对象,当 npc 出现时创建一个 npc 对象。所有这些类都派生自生物类,并且都具有虚拟析构函数。因此,当我创建这些对象时,我将它们添加到重载 operator() 的生物向量(不是实际的 STL 向量,而是定制的模板)中。为了方便展示,我写了这个虚拟代码。

vector<Creature *> CreatureList(100);

template <typename T>
struct vector {
    vector(int InitialSize);
    int InitialSize;
    T& operator()(int i);
    T* Entry; // At constructor, this is 'Entry = new T[InitialSize];' and is deleted at destructor.
};

struct Creature {
    Creature();
    virtual ~Creature();
    bool IsOnMap;
    char Name[30];
};

struct Player : Creature {
    Player();
    virtual ~Player();
    int PlayerState;
    int PlayerID;
};

struct Monster : Creature {
    Monster();
    virtual ~Monster();
    int SpawnPosX, SpawnPosY;
    int Health;
};

struct NPC : Creature {
    NPC();
    virtual ~NPC();
    Object TradeChest;
    int SpawnPosX, SpawnPosY;
};

int OnPlayerLogin() {
    Player *pl = new Player;
    CreatureList(NextCreatureID++) = pl;
    return PlayerID;
}

void OnMonsterSpawn() {
    Monster *mn = new Monster;
    CreatureList(NextCreatureID++) = mn;
}

void OnNPCSpawn() {
    NPC *npc = new NPC;
    CreatureList(NextCreatureID++) = npc;
}

void ProcessAllCreatures() {
    for (int i = 0; i < NextCreatureID; i++) {
        Creature* cr = CrList(i); // this doesn't return Creature* but actually Creature*&
        if (!cr)
            continue;

        if (!cr->IsOnMap)
            delete cr; // This spits a SIGSEGV (Segmentation fault).
    }
}

这个虚拟代码假定所有初始化都在构造函数中完成。 NextCreatureID 只是一个用作索引的自增变量。自定义向量类只是一个可自动调整大小的数组,operator() 将始终返回对实际对象的引用(由于内部代码约定,这无法更改)。

问题是它向进程发送了一个 SIGSEGV,如果我尝试delete &amp;cr,我会因为指针无效而得到 SIGABRT。那么,有什么方法可以解决这个问题而无需更改矢量类? (这对我来说是不可能的,因为合作。按我说的工作)。

【问题讨论】:

    标签: c++ pointers memory-management memory-leaks polymorphism


    【解决方案1】:
    if (!cr)
        continue;
    

    不会像你想要的那样工作。 delete 指针不会将其重置为 nullptr。在您第一次调用 ProcessAllCreatures() 时,一切都可能正常,当您第二次调用它时,您将删除已删除的指针,因为在查看已删除的指针时您永远不会 continue

    【讨论】:

    • 我犯了这么愚蠢的错误。我将不得不重新阅读那本旧的指针书。我已将此标记为答案。
    猜你喜欢
    • 2021-02-27
    • 2010-10-15
    • 1970-01-01
    • 2016-10-27
    • 2018-09-12
    • 1970-01-01
    • 2013-10-13
    • 1970-01-01
    相关资源
    最近更新 更多