C ++ Delete []导致程序崩溃

时间:2018-08-11 04:04:59

标签: c++

当我在析构函数中没有调用delete [] buf的程序时,我的程序运行良好。但是,当我包含它时,程序在输出开始时崩溃。 这是我的文件。

// string.cpp     #include“ String.h”     #包括     #包括     下游csis;

String::String() {
    buf = "\0";
    length = 0;
}

String::String(const char* tar) {
    int temp = strlen(tar);
    length = temp;
    buf = new char[length + 1];
    buf[length] = '\0';
    for (int i = 0; i < length; i++){
        buf[i] = tar[i];
    }
}

String::String(char a) {
    length = 1;
    buf = new char[length+1];
    buf[length] = '\0';
    buf[0] = a;
}

String::String(int x) {
    int alloc = x;
    if (x < 0) {
        alloc = 0;
    }
    buf = new char[alloc+1];
    length = x;
    buf[0] = '\0';
}


String::String(const String& a) {

    length = a.length;

    buf = new char[length+1];

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

String::String(char a, int x) {
    buf = new char[x+1];
    for (int i = 0; i < x; i++) {
        buf[i] = a;
    }
    buf[x] = '\0';
    length = strlen(buf);
}

String::~String() {
    delete buf;
}


String& String::operator=(const String& tar) {
    buf = new char[tar.length+1];
    strcpy(buf, tar.buf);
    length = tar.length;
    buf[length] = '\0';
    return *this;
}

String& String::operator=(const char* chr) {
    buf = (char*)chr;
    length = int(strlen(chr));
    return *this;
}

String operator+(const String& a, const String& b) {
    String sum;
    int size = a.length + b.length;
    sum.buf = new char[size+1];
    sum.length = size;
    for (int i = 0; i < a.length; i++) {
        sum.buf[i] = a.buf[i];
    }
    int j = 0;
    for (int i = a.length; i < size; i++) {
        sum.buf[i] = b.buf[j];
        j++;
    }
    sum.buf[size] = '\0';
    return sum;
}

String operator+(const String& tar, const char* c) {
    String sum;
    int size = int(strlen(c)) + tar.length;
    sum.buf = new char[size+1];
    sum.length = size;

    for (int i = 0; i < tar.length; i++) {
        sum.buf[i] = tar.buf[i];
    }

    int j = 0;
    for (int i = tar.length; i < size; i++) {
        sum.buf[i] = c[j];
        j++;
    }
    sum.buf[size] = '\0';
    return sum;
}

String operator+(const char* c, const String& tar) {
    String sum;
    int size = int(strlen(c)) + tar.length;
    sum.buf = new char[size+1];
    sum.length = size;
    for (int i = 0; i < int(strlen(c)); i++) {
        sum.buf[i] = c[i];
    }
    int j = 0;
    for (int i = strlen(c); i < size; i++) {
        sum.buf[i] = tar.buf[j];
        j++;
    }
    sum.buf[size] = '\0';
    return sum;
}

String operator+(const String& tar, char c) {
    String sum;
    int size = 1 + tar.length;
    sum.buf = new char[size];
    sum.length = size;
    for (int i = 0; i < tar.length; i++) {
        sum.buf[i] = tar.buf[i];
    }
    int j = 0;
    for (int i = tar.length; i < size; i++) {
        sum.buf[i] = c;
        j++;
    }
    sum.buf[size] = '\0';
    return sum;
}

String operator+(char c, const String& tar) {
    String sum;
    int size = 1 + tar.length;
    sum.buf = new char[size+1];
    sum.length = size;
    for (int i = 0; i < 1; i++) {
        sum.buf[i] = c;
    }
    int j = 0;
    for (int i = 1; i < size; i++) {
        sum.buf[i] = tar.buf[j];
        j++;
    }
    sum.buf[size] = '\0';
    return sum;
}

String& String::operator+=(const String& tar) {
    String temp = *this;
    temp = temp + tar;
    *this = temp;
    return *this;
}

String& String::operator+=(const char c) {
    String temp = *this;
    temp = temp + c;
    *this = temp;
    return *this;
}

String String::operator+() const {
    String sum;
    sum.length = length;
    sum.buf = new char[sum.length+1];
    strcpy(sum.buf, buf);
    for (int i = 0; i < length; i++) {
        sum.buf[i] = toupper(buf[i]);
    }
    sum.buf[length] = '\0';
    return sum;
}

int operator==(const String & tar, const String& tar2) {
    int check = 0;
    if (strcmp(tar.buf, tar2.buf) == 0) {
        check += 1;
    }
    else if (strcmp(tar.buf, tar2.buf) != 0) {
        check = 0;
    }
    return check;
}

int operator!=(const String& tar, const String& tar2) {
    int check = 0;
    if (!(strcmp(tar.buf, tar2.buf) == 0)) {
        check += 1;
    }
    else if (!(strcmp(tar.buf, tar2.buf) != 0)) {
        check = 0;
    }
    return check;
}

int operator<(const String& a, const String& b) {
    int check = 0;
    if (a.length < b.length) {
        check += 1;
    }
    return check;
}

int operator<=(const String& a, const String& b) {
    int check = 0;
    if (a.length <= b.length) {
        check += 1;
    }
    return check;
}

int operator>(const String& a, const String& b) {
    int check = 0;
    if (a.length > b.length) {
        check += 1;
    }
    return check;
}

int operator>=(const String& a, const String& b) {
    int check = 0;
    if (a.length >= b.length) {
        check += 1;
    }
    return check;
}

char& String::operator[](int x) {
    int out;
    if (x >= 0 && x < length) {
        out = x;
    }
    else if (!(x >= 0 && x < length)) {
        int output = NULL;
        cout << "ERROR: Invalid Index with [] operator." << endl;
        csis << "ERROR: Invalid Index with [] operator." << endl;
        out = NULL;
    }
    return buf[out];
}

char* operator+(const String& a, int x) {
    return &a.buf[x];
}

char* operator+(int x, const String& a) {
    return &a.buf[x];
}

String String::operator++(int val) {
    String temp;
    temp = *this;
    for (int i = 0; i < temp.length; i++) {
        temp.buf[i] = temp.buf[i] + 1;
    }
    return temp;
}

String String::operator--(int val) {
    String temp;
    temp = *this;
    for (int i = 0; i < temp.length; i++) {
        temp.buf[i] = temp.buf[i] - 1;
    }
    return temp;
}

String String::operator++() {
    String temp = *this;
    for (int i = 0; i < temp.length; i++) {
        temp.buf[i] = (temp.buf[i] + 1);
    }
    return temp;
}

String String::operator--() {
    String temp = *this;
    for (int i = 0; i < temp.length; i++) {
        temp.buf[i] = (temp.buf[i] - 1);
    }
    return temp;
}

int String::getLength() {
    return length;
}


String String::substr(int a, int b) {
    String temp = *this;
    char *fill = new char[b+1];
    int i = a;
    int x = 0;
    while (x <= b) {
        fill[i] = temp.buf[i];
        i++;
        x++;
    }
    temp.buf = fill;
    temp.buf[length] = '\0';
    return temp;
}

void String::print() {
    cout << """";
    csis << """";
    for (int i = 0; i < length; i++) {
        cout << buf[i];
        csis << buf[i];
    }
    cout << """";
    csis << """";
    cout << "  Length: " << length << endl;
    csis << "  Length: " << length << endl;
}

ostream& operator<<(ostream& o, const String& tar) {
    for (int i = 0; i < tar.length; i++) {
        o << tar.buf[i];
    }
    return o;
}

这里是字符串。h

//string.h
#ifndef _STRING_H
#define _STRING_H
#include <iomanip>
#include <stdlib.h>
#include <iostream>
using namespace std;

class String {
protected:
    int length;
    char* buf;

public:
    String();
    String(const char*);
    String(char a);
    String(int x);
    String(const String&);
    String(char a, int x);
    ~String();
    // Operator Overload
    String& operator=(const String& tar);
    String& operator= (const char*);
    friend String operator+(const String& a, const String& b);
    friend String operator+(const String&, const char*);
    friend String operator+(const char* c, const String& tar);
    friend String operator+(const String&, char c);
    friend String operator+(char c, const String& tar);
    String& operator+=(const String& tar);
    String& operator+=(const char c);
    String operator+() const;
    friend int operator==(const String&, const String&);
    friend int operator!=(const String&, const String&);
    friend int operator<(const String&, const String&);
    friend int operator<=(const String&, const String&);
    friend int operator>(const String&, const String&);
    friend int operator>=(const String&, const String&);
    char& operator[](int);
    friend char* operator+(const String&, int);
    friend char* operator+(int, const String&);
    String operator++();
    String operator--();
    String operator++(int);
    String operator--(int);
    int getLength();
    String substr(int a, int b);
    void print();
    friend ostream& operator<<(ostream&, const String&);
};
#endif

这里是StringDriver.cpp

// StringDriver.cpp
// MATTHEW BUTNER
// ID: 011029756
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include "StringDriver.h"
using namespace std;
ofstream csis;

int main() {
    csis.open("csis.txt");
    test1();
    test2();
    test3();
    test4();
    test5();
    test6();
    test7();
    test8();
    test9();
    test10();
    test11();
    test12();
    test13();
    test14();
    test15();
    test16();
    test17();
    test18();
    test19();
    test20();
    csis.close();
}

void test1() {
    cout << "1. Testing S1: String default ctor." << endl << endl;
    csis << "1. Testing S1: String default ctor." << endl << endl;
    String s1;
    s1.print();
    wait();
}

void test2() {
    cout << "2. Testing S2: String one arg (char *) ctor." << endl << endl;
    csis << "2. Testing S2: String one arg (char *) ctor." << endl << endl;
    String s2("ABC");
    s2.print();
    wait();
}

void test3() {
    cout << "3. Testing S3: String one arg (char) ctor." << endl << endl;
    csis << "3. Testing S3: String one arg (char) ctor." << endl << endl;
    String s3('Z');
    s3.print();
    wait();
}

void test4() {
    cout << "4. Testing S4: String one arg (int) ctor." << endl << endl;
    csis << "4. Testing S4: String one arg (int) ctor." << endl << endl;
    String s4(10);
    s4.print();
    wait();
}

void test5() {
    cout << "5. Testing S5, T5: String copy ctor." << endl << endl;
    csis << "5. Testing S5, T5: String copy ctor." << endl << endl;
    String s5("Purple Rain");
    s5.print();
    String t5(s5);
    t5.print();
    wait();
}

void test6() {
    cout << "6. Testing S6: String two arg (char, int) ctor." << endl << endl;
    csis << "6. Testing S6: String two arg (char, int) ctor." << endl << endl;
    String s6('*', 10);
    s6.print();
    wait();
}

void test7() {
    cout << "7. Testing S7, T7, U7: String assignment." << endl << endl;
    csis << "7. Testing S7, T7, U7: String assignment." << endl << endl;
    String s7("Sally Ride"), t7, u7;
    t7 = u7 = s7;
    s7.print();
    t7.print();
    u7.print();
    wait();
}

void test8() {
    cout << "8. Testing S8: String assignment." << endl << endl;
    csis << "8. Testing S8: String assignment." << endl << endl;
    String s8("ABC");
    s8 = s8;
    s8.print();
    wait();
}

void test9() {
    cout << "9. Testing S9: Implicit type conversion." << endl << endl;
    csis << "9. Testing S9: Implicit type conversion." << endl << endl;
    String s9;
    s9 = "ABC";
    s9.print();
    wait();
}

void test10() {
    cout << "10. Testing S10, T10, U10: String concatenation." << endl << endl;
    csis << "10. Testing S10, T10, U10: String concatenation." << endl << endl;
    String s10("DEF");
    String t10('H');
    String u10("ABC" + s10 + "G" + t10 + 'I');
    u10.print();
    String v10('X' + u10);
    v10.print();
    wait();
}

void test11() {
    cout << "11. Testing S11, T11: String concatenation." << endl << endl;
    csis << "11. Testing S11, T11: String concatenation." << endl << endl;
    String s11('A');
    String t11("BC");
    s11 += s11 += t11 += 'D';
    s11.print();
    t11.print();
    wait();
}

void test12() {
    cout << "12. Testing S12, T12: String unary operator." << endl << endl;
    csis << "12. Testing S12, T12: String unary operator." << endl << endl;
    String s12("Unary +");
    String t12(+s12);
    s12.print();
    t12.print();
    s12 = +s12;
    s12.print();
    wait();
}

void test13() {
    cout << "13. Testing S13, T13: String comparison operators." << endl << endl;
    csis << "13. Testing S13, T13: String comparison operators." << endl << endl;
    String s13("ABC"), t13("ABCD");
    s13.print();
    t13.print();
    cout << endl;
    cout << "== " << (s13 == t13 ? "True" : "False") << endl;
    cout << "!= " << (s13 != t13 ? "True" : "False") << endl;
    cout << "<  " << (s13 <  t13 ? "True" : "False") << endl;
    cout << "<= " << (s13 <= t13 ? "True" : "False") << endl;
    cout << ">  " << (s13 >  t13 ? "True" : "False") << endl;
    cout << ">= " << (s13 >= t13 ? "True" : "False") << endl;
    csis << endl;
    csis << "== " << (s13 == t13 ? "True" : "False") << endl;
    csis << "!= " << (s13 != t13 ? "True" : "False") << endl;
    csis << "<  " << (s13 <  t13 ? "True" : "False") << endl;
    csis << "<= " << (s13 <= t13 ? "True" : "False") << endl;
    csis << ">  " << (s13 >  t13 ? "True" : "False") << endl;
    csis << ">= " << (s13 >= t13 ? "True" : "False") << endl;
    wait();
}

void test14() {
    cout << "14. Testing S14: Overloaded subscript operator." << endl << endl;
    csis << "14. Testing S14: Overloaded subscript operator." << endl << endl;
    String s14("C++ is fun.");
    for (int i = -1; i <= s14.getLength(); i++) {
        char& ch = s14[i];
        if (ch != '\0')
            ++ch;
    }
    s14.print();
    wait();
}

void test15() {
    cout << "15. Testing S15: Pointer notation." << endl << endl;
    csis << "15. Testing S15: Pointer notation." << endl << endl;
    String s15("ABCDE");
    for(int i = 0; i < s15.getLength(); i++)
        ++(*(s15+i));
    for (int j = 0; j < s15.getLength(); j++) {
        cout << *(j + s15);
        csis << *(j + s15);
    }
    cout << endl;
    csis << endl;
    wait();
}

void test16() {
    cout << "16. Testing S16, T16, U16, V16, W16, X16, Y16, Z16: Increment and decrement operators." << endl << endl;
    csis << "16. Testing S16, T16, U16, V16, W16, X16, Y16, Z16: Increment and decrement operators." << endl << endl;
    String s16("ABC");
    String t16(++s16);
    s16.print();
    t16.print();

    String u16("ABC");
    String v16(u16++);
    u16.print();
    v16.print();

    String w16("ABC");
    String x16(--w16);
    w16.print();
    x16.print();

    String y16("ABC");
    String z16(y16--);
    y16.print();
    z16.print();
    wait();
}

void test17() {
    cout << "17. Testing S17, T17: Substr function." << endl << endl;
    csis << "17. Testing S17, T17: Substr function." << endl << endl;
    String s17("All You Need Is Love"), t17;
    t17 = s17.substr(4, 8);
    s17.print();
    t17.print();
    wait();
}

void test18() {
    cout << "18. Testing S18, T18: Output function." << endl << endl;
    csis << "18. Testing S18, T18: Output function." << endl << endl;
    String s18("Red-");
    String t18("Green-");
    String u18("Blue");
    cout << s18 << t18 << u18;
    csis << s18 << t18 << u18;
    cout << endl;
    csis << endl;
    wait();
}

void test19() {
    cout << "19. Testing S19, T19, U19: ReverseString class." << endl << endl;
    csis << "19. Testing S19, T19, U19: ReverseString class." << endl << endl;
    ReverseString s19("Computer");
    ReverseString t19;
    t19 = ~s19;
    s19.print();
    t19.print();

    ReverseString u19(~~s19);
    u19.print();
    wait();
}

void test20() {
    cout << "20. Testing S20, T20, U20: CaseString class." << endl << endl;
    csis << "20. Testing S20, T20, U20: CaseString class." << endl << endl;
    CaseString s20("BaLLooN");
    CaseString t20;
    t20 = s20;
    s20.print();
    t20.print();
    CaseString u20(s20);
    u20.print();
    wait();
}

void wait() {
    char buf;
    cout << endl << "Press any key to continue." << endl;
    csis << endl << endl;
    cin.get(buf);
}

问题在于string.cpp中的析构函数,当我有一个空的析构函数时,一切都很好,但是当我包含delete buf时,它将使程序崩溃。另外,这是其他.h和.cpp文件:

//ReverseString.h
#ifndef _REVERSESTRING_H
#define _REVERSESTRING_H
#include "String.h"
#include <iostream>
class ReverseString : public String {
public:
    ReverseString();
    ReverseString(const ReverseString& tar);
    ReverseString(const char* c);
    ReverseString& operator=(const ReverseString&);
    ReverseString operator~();
};
#endif

下一个文件

//ReverseString.cpp
#include "ReverseString.h"
extern ostream csis;

ReverseString::ReverseString() : String() {
}

ReverseString::ReverseString(const ReverseString& tar) : String(tar) {
}

ReverseString::ReverseString(const char* c) : String(c) {
}

ReverseString& ReverseString::operator=(const ReverseString& tar) {

    length = tar.length;

    buf = tar.buf;

    buf[length] = '\0';



    return *this;
}

ReverseString ReverseString::operator~() {


    ReverseString reverse;

    reverse.length = length;
    reverse.buf = new char[length];

    int j = length - 1;
    for (int i = 0; i < length; i++) {
        reverse.buf[i] = buf[j];
        j--;

    }
    return reverse;
}

CaseString.h

#ifndef _CASESTRING_H
#define _CASESTRING_H
#include "String.h"
#include <iostream>
class CaseString : public String {
protected:
    char* upper;
    char* lower;
public:
    CaseString();
    CaseString(const CaseString& tar);
    CaseString(const char* c);

    CaseString& operator=(const CaseString& c);

    void print();

    ~CaseString();
};
#endif

CaseString.cpp

#include "CaseString.h"
#include <fstream>
extern ofstream csis;

CaseString::CaseString() : String() {
}

CaseString::CaseString(const CaseString& tar) : String(tar) {
    upper = tar.upper;
    lower = tar.lower;
    buf = tar.buf;
    length = tar.length;
}

CaseString::CaseString(const char* c) : String(c) {
    lower = new char[int(strlen(c))];
    upper = new char[int(strlen(c))];
    int losize = strlen(c);
    char* getLow = new char[losize];
    for (int i = 0; i < losize; i++) {
        getLow[i] = tolower(c[i]);
    }
    char* getHi = new char[losize];
    for (int i = 0; i < losize; i++) {
        getHi[i] = toupper(c[i]);
    }
    lower = getLow;
    upper = getHi;
    lower[losize] = '\0';
    upper[losize] = '\0';
}

CaseString& CaseString::operator=(const CaseString& tar) {
    if (&tar != this) {
        String::operator=(tar);
        buf = tar.buf;
        length = tar.length;
        lower = tar.lower;
        upper = tar.upper;
    }
    return *this;
}

void CaseString::print() {
    cout << "\"" << buf << "\"" << " " << "Length = " << length << "  |" << "Lower = " << lower << "  |" << "Upper = " << upper << endl;
    csis << "\"" << buf << "\"" << "  |" << "Length = " << length << "  |" << "Lower = " << lower << "  |" << "Upper = " << upper << endl;
}

CaseString::~CaseString() {
}

1 个答案:

答案 0 :(得分:2)

我看到了几个问题。

主要问题是您有时会向buf分配一个指向字符串的指针(您的默认构造函数就是这样的一个地方,并且至少还有一个)。这是您不想删除的指针。您需要始终为buf分配内存,或者需要某种方法来判断您是否拥有该指针,应该将其删除。

另一个问题是,由于您使用new [],因此需要在析构函数中使用delete [] buf

在复制构造函数中,您不会在上等缓冲区的末尾复制nul字节。