使用 g++ 编译器的 C++ 内存泄漏

C++ Memory Leak using g++ compiler

我正在为我的 C++ class 做一些家庭作业,但是我遇到了这个内存泄漏问题。

我四处寻找,但找不到问题的根源。我还发现奇怪的是,当我在 g++ 中编译它时,内存泄漏在整个程序有 运行.

之后结束,这可能很常见也可能不常见。

如果有人能为我指出正确的方向,那就太棒了。就像我说的,我是初学者。感谢您的帮助。

//--------------- MYSTRING.CPP ---------------
// The class definition for fractions.
//
// Michael Arciola

#include "mystring.h"
#include <typeinfo>


MyString::MyString() // -------------------------------------------------- // #1
{
    length = 0;
    data = new char[length + 1];
    data[0] = '[=10=]';
}

MyString::MyString(const char* s1)
{
    length = strlen(s1);
    data = new char[length + 1];

    for(int i = 0; i < length; i++) {
        data[i] = s1[i];
        //cout << s1[i];
        //cout << data[i];
    }

    data[length + 1] = '[=10=]';
}

MyString::MyString(int s1)
{
    int temp;
    char c = 'm';
    MyString final;
    int count = 0;
    length = 0;
    data = new char[length + 1];
    int s2;
    s2 = s1;

    while (s1 != 0) 
    {
        temp = s1 % 10;
        s1 = s1 / 10;
        c = temp + '0';     
        count++;
    }

    length = count;

    for (int i = length - 1; i >= 0; i--) 
    {
        temp = s2 % 10;
        s2 = s2 / 10;
        data[i] = temp + '0';       
    }


    data[count] = '[=10=]';

}

// Destructor   ----------------------------------------------------------- // #2
MyString::~MyString()
{
    delete [] data;
}

// Copy Constructor 
MyString::MyString(const MyString& s1)
{
    length = s1.length;
    data = new char[length + 1];

    for (int i = 0; i < length; i++) 
    {
        data[i] = s1.data[i];
    }

    data[length + 1] = '[=10=]';
}

// Assignment Operator
MyString& MyString::operator=(const MyString& s1)
{
    if (this != &s1)
    {
        delete [] data;

        length = s1.length;
        data = new char[length + 1];

        for (int i = 0; i < length; i++) 
        {
            data[i] = s1.data[i];
        }

        data[length + 1] = '[=10=]';
    }

    return *this;
}

ostream& operator<< (ostream& os, const MyString& s1) // --------------- -// #3
{
    for (int i = 0; i < s1.length; i++)
    {
        os << s1.data[i];
    }

    return os;
}

istream& operator>> (istream& is, MyString& s1) 
{
    // NEED HELP

    /*
    is >> s1;

    return is;
    */
}

istream& getline (istream& is, MyString& s1, char delim)    
{
    // NEED HELP
} 

bool operator< (const MyString& s1, const MyString& s2)  // ------------- // #4
{
    if (strcmp(s1.data, s2.data) < 0) {
        return true;
    } else {
        return false;
    }
}

bool operator> (const MyString& s1, const MyString& s2)
{
    return s2 < s1;
}

bool operator<=(const MyString& s1, const MyString& s2) 
{
    return !(s2<s1);
}

bool operator>=(const MyString& s1, const MyString& s2)
{
    return !(s1<s2);
}

bool operator==(const MyString& s1, const MyString& s2)
{
    return (s1<=s2) && (s1>=s2);
}

bool operator!=(const MyString& s1, const MyString& s2) 
{
    return !(s1==s2);
}  

MyString operator+ (const MyString& s1, const MyString& s2) // ------------ // #5
{
    MyString newstring;
    int len = s1.length + s2.length;

    newstring.grow(len);

    for (int i = 0; i < s1.length; i++)
    {
        newstring.data[i] = s1.data[i];
    }

    for (int i = 0; i < s2.length; i++)
    {
        newstring.data[s1.length + i] = s2.data[i];
    }


    return newstring;
}

MyString& MyString::operator+=(const MyString& s1) 
{
    int start = length;
    int growth = s1.length;
    int totallen = s1.length + length;

    grow(growth, start);

    cout << "Start: " << start << endl;
    cout << "Length: " << length << endl;

    for (int i = start; start < length; i++) 
    {
        cout << "data[i]: " << data[i] << endl;
        cout << "s1.data[i]: " << s1.data[i] << endl;
        data[i] = s1.data[i];
    }
}

char& MyString::operator[] (unsigned int index) // ------------------------ // #6
{
    return data[index];
}

const char& MyString::operator[] (unsigned int index) const
{
    return data[index];
}

int MyString::getLength() const // ------------------------------------------ // #7
{
    return length;
}

const char* MyString::getCString() const
{
    return data; 
}

MyString MyString::substring(unsigned int start) const // ------------------------- // #8
{
    MyString temp;

    for (int i = start; i < length; i++) 
    {
        temp.data[i] = data[i];
        cout << temp.data[i];
    }

    return temp;
}

MyString MyString::substring(unsigned int start, unsigned int size) const
{
    MyString temp;

    if (size + start > length) {
        size = length;
    } else {
        size += start;
    }

    for (int i = start; i < size; i++) 
    {
        if (i != size)
        {
            temp.data[i] = data[i];
            cout << temp.data[i];
        }
    }

    return temp;
}

MyString& MyString::insert(unsigned int index, const MyString& s) // ---------- // #9
{
    if (index > length) {
        index = length;
    }

    grow(s.length, index);
    int len = s.length;
    int ph = 0;

        for (int i = index; i < index + len; i++) {
            data[i] = s.data[ph];
            ph += 1;
        }
}

int MyString::indexOf(const MyString& s) const // ------------------------------// #10
{
    int final;

    if (strstr(data, s.data) == 0) {
        final = -1;
    } else {
        final = strstr(data, s.data) - data;
    }

    return final;
}

void MyString::grow(int len) {

    char* temp = new char[length + len + 1];

    for (int i = 0; i < length; i++) 
    {
        temp[i] = data[i];
    }

    /* FOR TESTING
    for (int i = length; i < length + len; i++)
    {
        temp[i] = 'm';
    }
    */

    temp[length + len + 1] = '[=10=]';

    data = temp;
    length = length + len + 1;
}

void MyString::grow(int len, int index) {

    char* temp = new char[length + len + 1];
    int ph = 0;

    for (int i = 0; i < index; i++) 
    {
        temp[i] = data[i];
        ph += 1;
    }

    for (int i = index; i < index + len; i++)
    {
        temp[i] = ' ';
    }

    for (int i = index + len; i < length + len + 1; i++)
    {
        temp[i] = data[ph];
        ph += 1;
    }

    temp[length + len + 1] = '[=10=]';

    data = temp;
    length = length + len + 1;
}

void MyString::reverse() {

    char temp;

    for (int i = 0; i < length/2; i++) { // Loops through array, add value to temp, and move it to the other side of the array
        temp = data[i]; 
        data[i] = data[length - i -1];
        data[length - i -1] = temp;
        cout << data[i] << endl;

    }

}

这是我收到的错误。

*** glibc detected *** a.out: double free or corruption (!prev): 0x000000001323d0a0 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3b0de714af]
/lib64/libc.so.6(cfree+0x4b)[0x3b0de757ab]
a.out(__gxx_personality_v0+0x38b)[0x400d1b]
a.out[0x402208]
/lib64/libc.so.6(__libc_start_main+0xf4)[0x3b0de1d9f4]
a.out(__gxx_personality_v0+0x49)[0x4009d9]
======= Memory map: ========
00400000-00403000 r-xp 00000000 00:1e 30277703                           /home/majors/arciola/COP3330/assignment5/a.out
00603000-00604000 rw-p 00003000 00:1e 30277703                           /home/majors/arciola/COP3330/assignment5/a.out
1323d000-1325e000 rw-p 1323d000 00:00 0                                  [heap]
3b0da00000-3b0da1c000 r-xp 00000000 08:02 10128338                       /lib64/ld-2.5.so
3b0dc1c000-3b0dc1d000 r--p 0001c000 08:02 10128338                       /lib64/ld-2.5.so
3b0dc1d000-3b0dc1e000 rw-p 0001d000 08:02 10128338                       /lib64/ld-2.5.so
3b0de00000-3b0df4f000 r-xp 00000000 08:02 10128359                       /lib64/libc-2.5.so
3b0df4f000-3b0e14f000 ---p 0014f000 08:02 10128359                       /lib64/libc-2.5.so
3b0e14f000-3b0e153000 r--p 0014f000 08:02 10128359                       /lib64/libc-2.5.so
3b0e153000-3b0e154000 rw-p 00153000 08:02 10128359                       /lib64/libc-2.5.so
3b0e154000-3b0e159000 rw-p 3b0e154000 00:00 0 
3b0e200000-3b0e282000 r-xp 00000000 08:02 10128554                       /lib64/libm-2.5.so
3b0e282000-3b0e481000 ---p 00082000 08:02 10128554                       /lib64/libm-2.5.so
3b0e481000-3b0e482000 r--p 00081000 08:02 10128554                       /lib64/libm-2.5.so
3b0e482000-3b0e483000 rw-p 00082000 08:02 10128554                       /lib64/libm-2.5.so
2b79d5f7d000-2b79d5f80000 rw-p 2b79d5f7d000 00:00 0 
2b79d5fb1000-2b79d609c000 r-xp 00000000 08:05 3852142                    /usr/local/lib64/libstdc++.so.6.0.10
2b79d609c000-2b79d629c000 ---p 000eb000 08:05 3852142                    /usr/local/lib64/libstdc++.so.6.0.10
2b79d629c000-2b79d62a3000 r--p 000eb000 08:05 3852142                    /usr/local/lib64/libstdc++.so.6.0.10
2b79d62a3000-2b79d62a5000 rw-p 000f2000 08:05 3852142                    /usr/local/lib64/libstdc++.so.6.0.10
2b79d62a5000-2b79d62b8000 rw-p 2b79d62a5000 00:00 0 
2b79d62b8000-2b79d62ce000 r-xp 00000000 08:05 3852164                    /usr/local/lib64/libgcc_s.so.1
2b79d62ce000-2b79d64cd000 ---p 00016000 08:05 3852164                    /usr/local/lib64/libgcc_s.so.1
2b79d64cd000-2b79d64ce000 rw-p 00015000 08:05 3852164                    /usr/local/lib64/libgcc_s.so.1
2b79d64ce000-2b79d64d0000 rw-p 2b79d64ce000 00:00 0 
7fff51c4e000-7fff51c63000 rw-p 7ffffffe9000 00:00 0                      [stack]
7fff51dfd000-7fff51e00000 r-xp 7fff51dfd000 00:00 0                      [vdso]
ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0                  [vsyscall]
Abort

您的 grow() 方法分配一个新数组,并用该数组替换 data,而不 delete[]ing data 的先前内容。那是你的漏洞。

此外,我还看到您的赋值运算符中存在不可移植的未定义行为。比较指向两个对象的指针是未定义的行为,除非对象属于同一个数组或向量。