删除关键字导致程序崩溃

时间:2018-03-24 12:48:15

标签: c++ memory-management data-structures

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

UPDATE `wp_postmeta` 
SET `meta_value` = REPLACE(`meta_value`, 'jwp-test/' , '') 
WHERE `meta_value` LIKE '%jwp-test/%'

蝴蝶鱼类基于鱼类。

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;
}

鱼可以记住预定容量的琴弦。蝴蝶鱼类具有特殊的技能,它可以记住它看到的每一个字母以及看到它们的次数。当第二个内存已满时,它的第二个内存容量可以使其容量翻倍。

这些是类声明。

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";
        }
    }

}

1 个答案:

答案 0 :(得分:2)

让我们仔细看看这个功能的部分

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 true ,您将超出已分配的内存范围。

更改初始条件
if (m_used != (m_capa - 1))

if (m_used <= (m_capa - 1))

不要else if (...),只是简单else

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