簡體   English   中英

在 ConsoleApplication5.exe 中的 0x0F640E09 (ucrtbased.dll) 處拋出異常:0xC0000005:訪問沖突寫入位置 0x014C3000?

[英]Exception thrown at 0x0F640E09 (ucrtbased.dll) in ConsoleApplication5.exe: 0xC0000005: Access violation writing location 0x014C3000?

我剛剛編譯了這段代碼,它向我顯示了這個錯誤:
在 ConsoleApplication5.exe 中的 0x0F640E09 (ucrtbased.dll) 處拋出異常:0xC0000005:訪問沖突寫入位置 0x014C3000。 我真的不知道這個錯誤意味着什么,因為我剛剛使用 C++ 幾個月,我也嘗試在任何其他網站上尋找幫助,但我沒有找到任何幫助。

對於此代碼,我只允許使用 c-string 函數和<cstring>庫。 我不能使用字符串對象或包含庫。 我也可以使用輔助方法/函數。

#include <iostream>
#include <cstring>
#include <fstream>
using namespace std;

class MyString {
public:

    //default constructor
    MyString();

    MyString(char* chars);

    //copy constructor
    MyString(const MyString &);

    int length() const;

    //destructor
    ~MyString();

    //operator overloads
    char& operator[](int index);
    friend MyString operator+(const MyString& newWord, const MyString& newWord2);
    MyString& operator+=(const MyString& newWord);
    friend ostream& operator<<(ostream& newWord, const MyString& newWord2);
    friend istream& operator >> (istream& newWord, MyString& newWord2);
    friend bool operator==(const MyString& newWord, const MyString& newWord2);
    friend bool operator!=(const MyString& newWord, const MyString& newWord2);
    friend bool operator<(const MyString& newWord, const MyString& newWord2);
    friend bool operator<=(const MyString& newWord, const MyString& newWord2);
    friend bool operator>(const MyString& newWord, const MyString& newWord2);
    friend bool operator>=(const MyString& newWord, const MyString& newWord2);

private:
    char* value;
    int size;
};

//default constructor
MyString::MyString() {

    value = 0;
    size = 0;
}

//copy constructor
MyString::MyString(const MyString& newWord) {

    //perform a deep copy to copy each of the value to a new memory
    size = newWord.size;
    value = new char[size];

    for (int ii = 0; ii < size; ii++) {
        value[ii] = newWord.value[ii];
    }
}

//constructor with an argument
MyString::MyString(char* chars) {

    size = strlen(chars);
    value = new char[size];
    for (int i = 0; i < size; i++) {
        value[i] = chars[i];
    }

}

//find length
int MyString::length() const {

    return size;
}

//find the value of each index
char& MyString::operator[](int index) {

    return value[index];
}

//operator + (concatenate)
MyString operator+(const MyString& newWord, const MyString& newWord2) {

    MyString concatenated;
    concatenated = strcat(newWord.value, newWord.value);
    return concatenated;

}

//operator += (append)
MyString& MyString::operator+=(const MyString& newWord) {

    char * newMemory = value;
    value = new char[strlen(value) + newWord.length() + 1];
    strcpy(value, newMemory);
    strcat(value, newWord.value);
    if (size != 0)
    {
        delete[] newMemory;
    }
    size = strlen(value);
    return *this;
}

//ostream operator
ostream& operator<<(ostream& newWord, const MyString& newWord2) {

    newWord << newWord2.value;
    return newWord;
}


//istream operator
istream& operator >> (istream& newWord, MyString& newWord2) {

    const int MAX = 100;
    char* ptr = new char[MAX];
    newWord >> ptr;
    newWord2 = MyString(ptr);
    delete ptr;
    return newWord;
}

//all boolean operators
bool operator==(const MyString& newWord, const MyString& newWord2) {
    if (newWord.value == newWord2.value) {
        return true;
    }
    else {
        return false;
    }
}

bool operator!=(const MyString& newWord, const MyString& newWord2) {
    if (newWord.value != newWord2.value) {
        return true;
    }
    else {
        return false;
    }
}

bool operator<(const MyString& newWord, const MyString& newWord2) {
    if (newWord.value < newWord2.value) {
        return true;
    }
    else {
        return false;
    }
}

bool operator<=(const MyString& newWord, const MyString& newWord2) {
    if (newWord.value <= newWord2.value) {
        return true;
    }
    else {
        return false;
    }
}

bool operator>(const MyString& newWord, const MyString& newWord2) {
    if (newWord.value > newWord2.value) {
        return true;
    }
    else {
        return false;
    }
}

bool operator>=(const MyString& newWord, const MyString& newWord2) {
    if (newWord.value >= newWord2.value) {
        return true;
    }
    else {
        return false;
    }
}

//destructor to release memory
MyString::~MyString() {
    delete[] value;
}

void test_copy_and_destructor(MyString S) {
    cout << "test: copy constructor and destructor calls: " << endl;
    MyString temp = S;
    cout << "temp inside function test_copy_and_destructor: " << temp << endl;
}

int main() {

    MyString st1("abc abc");
    MyString st2("9fgth");

    cout << "Copy constructor , << operator" << endl;

    MyString  st3(st1);

    cout << "st3: " << st3 << endl;

    test_copy_and_destructor(st2);

    MyString  st4;

    cout << "operator + " << endl;

    st4 = st3 + st2;

    cout << "st4: " << st4 << endl;

    cout << "st1 + st2: " << (st1 + st2) << endl;

    cout << "operators  [ ] " << endl;

    for (int i = 0; i < st2.length(); i++)
        cout << st2[i] << " ";

    cout << endl;

    cout << "operators  += , ==, != " << endl;

    st2 += st1;

    if (st3 == st1)
        cout << "st3 and st1 are identical " << endl;
    else cout << "st3 and st1 are not identical " << endl;

    if (st2 != st1)
        cout << "st2 and st1 are not identical " << endl;
    else cout << "st2 and st1 are identical " << endl;

    cout << "operators  < , <=, >, >= " << endl;

    if (st2 < st1)
        cout << "st2 < st1 " << endl;
    else cout << "st2 is not less than st1 " << endl;

    if (st1 <= st2)
        cout << "st1 <= st2 " << endl;
    else cout << "st1 is not less than or equal to st2 " << endl;

    if (st1 > st2)
        cout << "st1 > st2 " << endl;
    else cout << "not (st1 >  st2) " << endl;

    if (st1 >= st2)
        cout << "st1 >= st2 " << endl;
    else cout << "not (st1 >=  st2) " << endl;

    cout << "operator >> " << endl;

    //Open the data file
    ifstream input("A9_input.txt");
    if (input.fail()) {
        cout << "unable to open input file A9_input.txt, Exiting..... ";
        system("pause");
        return 0;
    }
    MyString temp1;
    MyString temp2("aaa");
    input >> temp1;
    input >> temp2;
    cout << "first element of input file: " << temp1 << endl;
    cout << "second element of input file: " << temp2 << endl;
    input.close();

    cout << "MyString says farewell....." << endl;
    system("pause");
    return 0;
}

您的錯誤很可能出現在以下代碼中:

st4 = st3 + st2; # note that you initialize st4 with type MyString but inside operator+ you assign a char[] to MyString. Just letting you know since you dont have a operator= overloaded function 

調用:

MyString operator+(const MyString& newWord, const MyString& newWord2) {

    MyString concatenated;
    concatenated = strcat(newWord.value, newWord.value); # you have an mistake here, second parameter should be newWord2.value
    return concatenated;

}

您假設您的 newWord.value 擁有足夠的空間來保存 newWord.value 和 newWord2.value。 但並不是你在構造函數上將它初始化為 newWord.value 所以你基本上是在寫入一個違反內存訪問的區域。 您想要做的是使 newWord 足夠大以容納兩個字符串。

對 strcat 的引用: http ://www.cplusplus.com/reference/cstring/strcat/

您的operator +正在寫入超出分配的內存(緩沖區溢出)。 您可以輕松地將其更改為非常簡單的:

MyString operator +(const MyString& newWord, const MyString& newWord2) {
    MyString concatenated;
    return concatenated += newWord2;
}

那么它甚至不需要成為班級的friend

operator +=也是錯誤的,因為您的字符串最初不是以 NULL 終止的方式創建的,因此實際上您根本不應該使用strlen()strcpy()strcat() ,因為您隨后將任意內存連接在一起(讀取過去分配的內存也可能出現段錯誤)。 因此,您應該考慮是否希望字符串 NULL 終止(並以此方式使用)。

無論如何, operator +=也沒有被非常有效地定義,例如:

MyString& MyString::operator+=(const MyString& newWord) {
    size_t newSize = size + newWord.size;
    char * newValue = new char[newSize /* + 1 */]; // not null terminated, but cannot be printed easily then
                                          // or make the string initially null terminated and then allocate +1 and null terminate then
    memcpy(newValue, value, size);
    memcpy(newValue + size, newWord.value, newWord.size /* + 1 */);
    delete[] value;
    value = newValue;
    size = newSize;
    return *this;
}

看? 不使用遍歷字符串的strlen() (在您的情況下不是空終止),因為無論如何您都知道字符串的大小。 您還可以在構造函數中使用memcpy()而不是for (int i = 0; i < size; i++)循環。 strcpy()並使字符串以空字符結尾(但即使如此, memcpy()也可以使用,因為它更快 - 不會在復制的每個字符上測試'\\0' )。

運算符== , !=似乎也不太正確,因為只比較指針(因此字符串只會等於自身,而不等於其他具有存儲在value的相同字符的字符串)。

此外,由於初始字符串不是空終止, operator <<也不會正常工作(將打印出超出字符串的任意內存)。 通常,我建議讓字符串value始終以空結尾,以避免出現一些問題。

最后,您肯定需要定義operator = ,因為現在您使用的是默認的淺拷貝,因此使用此代碼,您將在銷毀st4 (以及任何其他分配給=字符串時獲得雙重釋放)。 請注意,正確實現operator =也很棘手 - 請注意自分配場景。

您的代碼還有其他問題,大多數與您的比較運算符有關。

MyString operator <operator==不正確。 要比較 c 樣式的字符串,請使用strcmp ,而不是== 相反,您的比較運算符正在比較指針值,而不是所指向的數據。


第二個問題是您需要做的就是完全實現operator <operator == ,因為所有其他比較運算符都可以根據這些函數來實現。

把這些放在一起,你的類的實現應該是這樣的:

#include <cstring>
//...     
class MyString {
public:
    //...    
    friend bool operator==(const MyString& newWord, const MyString& newWord2);
    friend bool operator!=(const MyString& newWord, const MyString& newWord2);
    friend bool operator<(const MyString& newWord, const MyString& newWord2);
    friend bool operator<=(const MyString& newWord, const MyString& newWord2);
    friend bool operator>(const MyString& newWord, const MyString& newWord2);
    friend bool operator>=(const MyString& newWord, const MyString& newWord2);

private:
    char* value;
    int size;
};

bool operator==(const MyString& newWord, const MyString& newWord2) 
{ return strcmp(newWord.value, newWord2.value) == 0; } 

bool operator<(const MyString& newWord, const MyString& newWord2) 
{ return strcmp(newWord.value, newWord2.value) == -1; }

bool operator!=(const MyString& newWord, const MyString& newWord2)
{ return !(newWord == newWord2); }

bool operator<=(const MyString& newWord, const MyString& newWord2)
{ return !(newWord2 < newWord); }   

bool operator> (const MyString& newWord, const MyString& newWord2)
{ return newWord2 < newWord; }

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

請注意,運算符使用<==來實現其他運算符。


第三個問題是您缺少賦值運算符

MyString& operator=(const MyString&)

如果沒有這個函數,你就不能在不破壞內存的情況下相互分配MyString對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM