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

删除导致程序崩溃的关键字

  •  1
  • MaxAttax  · 技术社区  · 6 年前

    我创建了一个类,该类为通过析构函数删除的数组使用分配的内存。出于某种原因,我使用new关键字创建了一个指向此类变量的指针,当我试图删除它时,我的程序崩溃并出现堆损坏错误。

    int main() {
        Butterflyfish *tad
            = new Butterflyfish(3, "tad");
        tad->printMemory();
        tad->remember('a');
        tad->remember('x');
        tad->remember('a');
        tad->remember('b');
        tad->remember('c');
        tad->remember('a');
        tad->remember('d');
        tad->printMemory();
        tad->forget();
        tad->printMemory();
        delete tad; //causes crash
        return 0;
    }
    

    蝴蝶鱼是以鱼类为基础的。

    Fish::Fish(int capacity, std::string name)
    {
        if (capacity < 0)
        {
            capacity = 3;
        }
    
        this->m_memory = new char[capacity];
    
        for (int i = 0; i < capacity; i++)
        {
            this->m_memory[i] = '.';
        }
    
        this->m_capa = capacity;
        this->m_used = 0;
        this->m_name = name;
        this->m_full = false;
    
    }
    
    Fish::Fish(const Fish& other)
    {
        this->m_name = other.m_name;
        this->m_capa = other.m_capa;
        this->m_used = other.m_used;
        this->m_full = other.m_full;
    
        this->m_memory = new char[m_capa];
    
        for (int i = 0; i < this->m_capa; i++)
        {
            this->m_memory[i] = other.m_memory[i];
        }
    
    }
    
    Fish::~Fish()
    {
        delete[] m_memory;
    }
    
    Fish& Fish::operator=(const Fish& other)
    {
        // TODO: insert return statement here
    
        if ( this == &other )
        {
            return *this;
        }
    
        this->m_name = other.m_name;
        this->m_capa = other.m_capa;
        this->m_used = other.m_used;
        this->m_full = other.m_full;
    
        this->m_memory = new char[m_capa];
    
        for (int i = 0; i < this->m_capa; i++)
        {
            this->m_memory[i] = other.m_memory[i];
        }
    
        return *this;
    }
    
    void Fish::remember(char c)
    {
        if (m_used != (m_capa - 1))
        {
            for (int i = m_used; i >= 0; i--)
            {
                this->m_memory[i + 1] = this->m_memory[i];
            }
    
            this->m_memory[0] = c;      
            this->m_used++;
        }
    
        else if (this->m_used == (this->m_capa - 1))
        {
            if (this->m_full)
            {
                for (int i = m_used; i > 0; i--)
                {
                    this->m_memory[m_used] = this->m_memory[m_used - 1];
                }
    
                this->m_memory[0] = c;
            }
            else
            {
                for (int i = m_used; i > 0; i--)
                {
                    this->m_memory[i] = this->m_memory[i - 1];
                }
    
                this->m_memory[0] = c;
                this->m_used = this->m_capa;
    
                this->m_full = true;
            }
        }
    
    }
    
    void Fish::forget()
    {
        for (int i = 0; i < m_capa; i++)
        {
            this->m_memory[i] = '.';
        }
    
        this->m_used = 0;
        this->m_full = false;
    }
    
    void Fish::printMemory() const
    {
        std::cout << "{ ";
    
        for (int i = 0; i < m_capa; i++)
        {
            std::cout << this->m_memory[i] << " ";
        }
    
        std::cout << '}' << std::endl;
    }
    
    std::string Fish::getName()
    {
        return this->m_name;
    }
    
    const char* Fish::getMemory() const
    {
        return m_memory;
    }
    
    int Fish::getAmount() const
    {
        return this->m_used;
    }
    
    int Fish::getCapacity() const
    {
        return this->m_capa;
    }
    

    fish类在测试时没有错误,因此只有在您想使用它时才适用。这是蝶鱼课。

    Butterflyfish::Butterflyfish(int capacity, std::string name) : Fish(capacity, name)
    {
        m_extended = new OBBY[capacity];
        m_exUsed = 0;
        m_exCapa = capacity;
    }
    
    Butterflyfish::Butterflyfish(const Butterflyfish &other) : Fish(other)
    {
        this->m_exCapa = other.m_exCapa;
        this->m_exUsed = other.m_exUsed;
        this->m_extended = new OBBY[this->m_exCapa];
    
        for (int i = 0; i < m_exUsed; i++)
        {
            this->m_extended[i].letter = other.m_extended[i].letter;
            this->m_extended[i].times = other.m_extended[i].times;
        }
    }
    
    Butterflyfish& Butterflyfish::operator=(const Butterflyfish &other)
    {
        if (this == &other)
        {
            return *this;
        }
        else
        {
            Fish::operator=(other);
    
            this->m_exCapa = other.m_exCapa;
            this->m_exUsed = other.m_exUsed;
            this->m_extended = new OBBY[this->m_exCapa];
    
            for (int i = 0; i < m_exUsed; i++)
            {
                this->m_extended[i].letter = other.m_extended[i].letter;
                this->m_extended[i].times = other.m_extended[i].times;
            }
    
            return *this;
        }
    }
    
    Butterflyfish::~Butterflyfish()
    {
        delete[] m_extended;
    }
    
    void Butterflyfish::remember(char c)
    {
        Fish::remember(c);
    
        tolower(c);
    
        if (m_exUsed == m_exCapa)
        {
            OBBY* temp = new OBBY[m_exCapa];
    
            for (int i = 0; i < m_exCapa; i++)
            {
                temp[i].letter = m_extended[i].letter;
                temp[i].times = m_extended[i].times;
            }
    
            delete[] m_extended;
    
            m_extended = new OBBY[m_exCapa * 2];
    
            for (int j = 0; j < m_exUsed; j++)
            {
                m_extended[j].letter = temp[j].letter;
                m_extended[j].times = temp[j].times;
            }
    
            m_exCapa *= 2;
    
            delete[] temp;
        }
    
        if (m_exUsed == 0)
        {
            m_extended[0].letter = c;
            m_extended[0].times = 1;
    
            m_exUsed = 1;
        }
        else
        {
            bool match = false;
    
            for (int i = 0; i < m_exUsed; i++)
            {
                if ( m_extended[i].letter == c )
                {
                    m_extended[i].times += 1;
                    match = true;
                    break;
                }
            }
    
            if (match == false)
            {
                m_extended[m_exUsed].letter = c;
                m_extended[m_exUsed].times += 1;
                m_exUsed += 1;
            }
        }
    
    }
    
    void Butterflyfish::printMemory() const
    {
        Fish::printMemory();
    
        std::cout << "I'm Obnoxious" << std::endl;
    
        if (m_exUsed == 0)
        {
            return;
        }
    
        std::cout << "I've Seen" << "\n\t";
        for (int i = 0; i < m_exUsed; i++)
        {
            if (i == (m_exUsed - 1))
            {
                std::cout << "and " << m_extended[i].letter << " " << m_extended[i].times << " times\n";
            }
            else
            {
                std::cout << m_extended[i].letter << " " << m_extended[i].times << " times\n\t";
            }
        }
    
    }
    

    鱼可以记住预定容量的字符串。蝶鱼类有特殊的技能,它可以记住看到的每个字母以及看到它们的次数。当它的第二个内存已满时,它的第二个内存容量可以加倍。

    这些是类声明。

    class Fish {
    private:
        // TODO: declare any private member variables/functions here
        char* m_memory;
        int m_used, m_capa;
        bool m_full;
        std::string m_name;
    }; //left out public stuff cuz It's posted up there
    
    class Butterflyfish :public Fish {
    private:
        struct OBBY //for obnoxious
        {
            char letter = ' ';
            int times = 0;
        };
    
        OBBY* m_extended;
        int m_exCapa;
        int m_exUsed;
    };
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Some programmer dude    6 年前

    让我们仔细看看这个函数的各个部分

    void Fish::remember(char c)
    {
        if (m_used != (m_capa - 1))
        {
            // ...
        }
    
        else if (this->m_used == (this->m_capa - 1))
        {
            if (this->m_full)
            {
                // ...
            }
            else
            {
                // ...
                this->m_used = this->m_capa;
                // ...
            }
        }
    }
    

    直到 m_used == m_capa - 1

    问题是,当这种情况发生时,您将设置 m_used = m_capa 。在下一次通话中 m_used != m_capa - 1 真的 您将超出分配的内存范围。

    将初始条件更改为

    if (m_used != (m_capa - 1))
    

    if (m_used <= (m_capa - 1))
    

    不要这样做 else if (...) ,很简单 else

    请注意,如果您学习了如何使用调试器逐行遍历代码,这一点将非常明显。